vue2.0实现双向数据绑定原理

vue2.0中通过利用Object.defineProperty方法监听属性的get和set方法来实现对数据的双向绑定,看如下示例:

<!DOCTYPE html>
<html>
<head>
<style> 

</style>
</head>
<body>
Name: <span id="txtName"></span>
<br />
<input id='inpName' type="text">
<script>
    let obj = {name: ''};
    let newObj = JSON.parse(JSON.stringify(obj));
    Object.defineProperty(obj, 'name', {
        get: function(){
            return newObj.name;
        }
        set: function(val){
            if(val === obj.name) return;            
            newObj.name = val;
            observer();
        }
    });

    function observer(){
        txtName.innerHTML = obj.name;
        inpName.value = obj.name; 
    }

    inpName.oninput = function(){
        obj.name = this.value;
    }

    setTimeout(() => {
        obj.name = 'Hello world';
    }, 2000);
</script>
</body>
</html>

上面代码中利用Object.defineProperty方法去监听obj对象的name属性的get和set方法。这里需要注意的是:需要对obj对象进行克隆,而在监听函数中的赋值取值操作均操作的是克隆后的对象newObj(避免死循环),因为如果操作原对象obj,这样在get方法中会读取name属性,而只要涉及到读取name属性就会被defineProperty函数监听,这样就造成了死循环。

当对obj的name属性设置值时,会触发set方法,将新值赋值给newObj的name属性同时将新值绑定到视图上,实现属性变视图变。另外需要绑定视图控件的oninput事件,当文本框中的内容发生变化时将新值赋值给obj的name属性同时又会触发监听函数,从而实现了数据的双向绑定。

vue3.0实现双向数据绑定原理

<!DOCTYPE html>
<html>
<head>
<style> 

</style>
</head>
<body>
Name: <span id="txtName"></span>
<br />
<input id='inpName' type="text">
<script>
    let obj = {name: ''};
    obj = new Proxy(obj, {
        get(target, prop){
            return target[prop];
        }
        
        set(target, prop, value){
            target[prop] = value;
            observer();
        }
    });
    function observer(){
        txtName.innerHTML = obj.name;
        inpName.value = obj.name; 
    }

    inpName.oninput = function(){
        obj.name = this.value;
    }

    setTimeout(() => {
        obj.name = 'Hello world';
    }, 2000);
</script>
</body>
</html>

3.0中的绑定原理与2.0中的原理基本一致都是通过监听属性值来改变视图值,然后通过视图的input事件而改变属性值。不同都是这里使用了ES6中的新语法Proxy来实现数据监听。

二者的区别

  • 2.0中使用的是Object.defineProperty实现对属性的监听。缺点是一定要克隆一个新的对象进行操作,否则就会造成死循环。第二个缺点是如果有多个属性,那么就要定义多个Object.defineProperty去分别监听每一个属性。
  • 3.0中使用了ES6中的新语法,用到了Proxy去实现监听,这样省去了克隆对象的步骤,同时不管有多少个属性只需要定义一次Proxy就可以实现多对象的监听,不同分别定义。

 

Logo

前往低代码交流专区

更多推荐