Vue的数据双向绑定原理——Object-defineProperty

一、定义

①方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。

②vue.js的双向数据绑定就是通过Object.defineProperty方法实现的,俗称属性拦截器。

二、语法

①语法

/*
 * @param: obj:需要定义属性的对象; 
 *         prop:需要定义或修改的属性;
 *         descriptor:将被定义或修改属性的描述符
*/
Object.defineProperty(obj,prop,descriptor)

②对象里目前存在的属性描述符主要有两种形式: 数据描述符和存取描述符

  • 数据描述符: 拥有可写或不可写值的属性
可选键值: 
configurable: 当且仅当configurable为true时,改属性描述符才能够被改变,也能被删除 
enumerable: 当其值为true时,该属性才能够出现在对象的枚举属性中,默认为false 
writable: 当且仅当该属性的值为true时,该属性才能被赋值运算符改变, 默认为false。 
value: 该属性对应的值,可以是任意有效的javascript的值(数值,对象,函数等),默认为undefined
  • 存取描述符: 由一对getter-setter函数功能来描述的属性
可选键值: 
configurable: 当且仅当configurable为true时,改属性描述符才能够被改变,也能被删除 
enumerable: 当其值为true时,该属性才能够出现在对象的枚举属性中,默认为false 
get: 给属性提供getter的方法,如果没有 getter 则为undefined。当我们读取某个属性的时候,其实是在对象内部调用了该 方法,此方法必须要有return语句。该方法返回值被用作属性值。默认为 undefined 
set:设置属性值的方法, 如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。也就是说,当我们设置某个属性的时候,实际上是在对象的内部调用了该方法

③示范:

        let user={
            foo:'bar'
        };
        user.age=18;
        user['name']='eric';
        Object.defineProperty(user,'gender',{
            // value:'男'
            // value 和get两者只能取其一,因为是矛盾的
            // get属性用于属性访问,当访问gender的时候,会自动调用get方法
            get:function(){
                console.log('取值操作了')
                return 123
            },
            // set 属性设置器,当设置user.gender=xxx,则会自动调用set方法,xxx作为set的参数
            set:function(value){
                console.log('赋值操作'+value)
            }
        });  
        // user.gender      取值操作了 123
        // user.gender=666  赋值操作666

三、例子

①设置user.age 如果要对age赋值,则限制age的取值范围:0-120之间

        var age=0;
        var user={};
        Object.defineProperty(user,'age',{
            //value:18,
            get:function(){
                return age;
            },
            set:function(val){
                if(val<0||val>120){
                    throw new Error('age invalid')
                }
                // 赋值(不能直接赋值,需要有一个中间变量)
                age=val;
            },
        });
        // user.age    0
        // user.age=1   1
        // user.age=-1  age invalid

当data.message的值改变的时候更新#test的视图

    <div id="test">这是一个测试</div>
    <script> 
        var view = document.getElementById("test");
        var data = {};
        var i = 0;
        Object.defineProperty(data, "message", {
            set: function (newValue) {
                //当data.message的值改变的时候更新#test的视图 
                view.textContent = newValue;
            },
        });
        setInterval(function () {
            i++;
            data["message"] = "data.message的值更新了,我要更新视图" + i;
        }, 1000); 
    </script>

原文地址:https://www.cnblogs.com/EricZLin/p/9372936.html