vue双向绑定的原理

vue实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。

在MDN上对该方法的说明是:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

它接收三个参数,要操作的对象,要定义或修改的对象属性名,属性描述符。重点就是最后的属性描述符。

属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。这两种对象只能选择一种使用,不能混合两种描述符的属性同时使用。上面说的get和set就是属于存取描述符对象的属性。

然后我们可以通过在存取描述符中的get和set方法内写入自定义的逻辑来实现对象获取属性和设置属性时的行为。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <input type="text" id="txt">
    <div id="box"></div>
</body>
<script>
    txt.oninput=function(){
        var keyValue = txt.value;
    var obj = {};
Object.defineProperty(obj,'key', {
    enumerable: true,
    configurable: true,
    get: function(){
        return keyValue;
    },
    set: function(newValue){
        keyValue = newValue;
        // console.log(`keyValue的值已发生改变,目前的值是:${keyValue}`);
    }
});
// console.log(obj.key);

console.log(keyValue); // "obj对象的key属性已经绑定了变量keyValue的值"
box.innerHTML=keyValue;

    }
    
// obj.key = 'obj对象的key属性已经绑定了变量keyValue的值';
// keyValue的值已发生改变,目前的值是:obj对象的key属性已经绑定了变量keyValue的值
// "obj对象的key属性已经绑定了变量keyValue的值"

    



</script>
</html>

上面这个例子就是改变了对象获取属性及设置属性的默认行为。

对象obj获取属性key的值时,会触发上面的get方法,得到的是变量keyValue的值,然后当重新设置key的值时,触发set方法,会将变量keyValue的值改变为设置的值,如此就实现了一个简单的双向绑定:改变keyValue,obj.key得到的值也会改变,重新设置obj.key,keyValue一样会随之改变。

当然,vue的双向绑定实际更复杂,但最基本的原理就是基于Object.defineProperty()方法改变数据存取的默认行为来实现的。

知识点扩展:

语法

Object.defineProperty(obj, prop, descriptor)

参数

obj

要在其上定义属性的对象。

prop

要定义或修改的属性的名称。

descriptor

将被定义或修改的属性描述符。

属性描述符

 

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。

数据描述符和存取描述符均具有以下可选键值:

configurable

当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false

enumerable

当且仅当该属性的enumerabletrue时,该属性才能够出现在对象的枚举属性中。默认为 false

数据描述符同时具有以下可选键值

value

该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined

writable

当且仅当该属性的writabletrue时,value才能被赋值运算符改变。默认为 false

存取描述符同时具有以下可选键值

get

一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。

默认为 undefined

set

一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。

详细请参考Object.defineProperty()具体用法:

地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

猜你喜欢

转载自blog.csdn.net/namechenfl/article/details/81587160