Vue数据代理的原理和实现
亦世凡华、 人气:0Object.defineProperty
defineProperty方法会直接在一个对象上定义一个新属性,或者修改另一个对象的现有属性,并返回此对象,通常使用 get 进行读取,用 set 进行修改。
注意:defineProperty定义的属性是不能进行枚举(不能参与遍历)的
<body> <script> let person = { name:'张三', sex:'男' } Object.defineProperty(person,'age',{ value:18 }) console.log(Object.keys(person)); console.log(person); </script> </body>
当然,defineProperty内部的属性我们自己控制,可以根据需求进行一定修改,如下:
Object.defineProperty(person,'age',{ value:18, enumerable:true, //控制属性是否可以枚举,默认值是false writable:true, //控制属性是否可以被修改,默认值是false configurable:true, //控制属性是否可以被删除,默认值是false })
definedProperty最重要的点就是get和set了,如下:
<script> let number = 18 let person = { name:'张三', sex:'男' } Object.defineProperty(person,'age',{ // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age值 get(){ console.log('有人读取了age属性'); return number }, // 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值 set(value){ console.log('有人修改了age属性,且值是',value); number = value } }) </script>
根据上文的简述,我们理解数据代理就是:通过一个对象代理对另一个对象中属性的操作(读/写)
<script> let obj = {x:100} let obj1 = {y:200} Object.defineProperty(obj1,'x',{ get(){ return obj.x }, set(value){ obj.x = value } }) </script>
那么在Vue中如何应用数据代理呢
<body> <div id="root"> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> </div> <script src="/Vue.js/vue.js"></script> <script> Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示 new Vue({ el:'#root', data:{ name:'张三', age:18 } }) </script> </body>
可以看出 vm 身上有我们data里面的name和age属性,所以当我们访问data上面的name或age的时候,getter开始工作;如果通过vm去修改这个name或age时,setter开始工作。即在data里面的数据是有自己的get和set,如下:
get的实现:很简单,当我们修改data.name的时候,我们在查看name的时候,name的值就是data.name的值,如下:
set的实现:当我们进行修改name的时候,直接在控制台修改name的值。
name的值的的确确是被修改了也渲染到页面上去了,但我们怎么保证是data.name里面的name也被真真修改了呢?现在分析一下,data里面的name到底改没改。
注意:我们不能直接在控制台输入data.name来查看,因为data仅仅是Vue里面配置项的一个属性,并不是全局变量,是不能进行访问的,如果访问会报下面这样的错误。
那么我们如何拿到data里面的name呢?在Vue中vm会把data里面的数据存在 _data 里面,所以说vm._data的data就是我们存放数据的data,那么如何验证呢?既然我们不能访问到Vue里面的data,那么我们把Vue里面的data的数据给写到全局变量里面,然后Vue再引用全局上的data,这样我们就可以验证,Vue自带的 _data 的数据是不是和Vue实例里面的data数据相等。
<script> Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示 let data = { name:'张三', age:18 } const vm = new Vue({ data }) vm.$mount('#root') // 接下来我们验证 vm._data = options.data = data 是不是true;options.data就是Vue里面配置项的data;data就是我们定义在外面的data console.log(Boolean(vm._data = vm.data = data)); //true </script>
数据代理说白了就是把data里面的数据放一份到 vm 上面,目的就是为了当编码更方便。
总结
Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
Vue中数据代理的好处:
更加方便的操作data中的数据
基本原理:
通过Object.defineProperty()把data对象上所有属性添加到vm上。为每个添加到vm上的属性都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。
加载全部内容