Vue响应式原理及总结
Vue 的响应式原理是核⼼是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get 和 set ⽅法,data 中声明的属性都被添加了访问器属性,当读取 data 中的数据时⾃动调⽤ get ⽅法,当修改 data 中的数据时,⾃动调⽤ set ⽅法,检测到数据的变化,会通知观察者 Wacher,观察者 Wacher⾃动触发重新render 当前组件(⼦组件不会重新渲染),⽣成新的虚拟 DOM 树,Vue 框架会遍历并对⽐新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上。
虚拟DOM (Virtaul DOM): ⽤ js 对象模拟的,保存当前视图内所有 DOM 节点对象基本描述属性和节点间关系的树结构。⽤ js 对象,描述每个节点,及其⽗⼦关系,形成虚拟 DOM 对象树结构。
项⽬中常遇到的关于vue响应式的记录与总结:
因为只要在 data 中声明的基本数据类型的数据,基本不存在数据不响应问题,所以重点介绍数组和对象在vue中的数据响应问题,vue可以检测对象属性的修改,但⽆法监听数组的所有变动及对象的新增和删除,只能使⽤数组变异⽅法及$set⽅法。
可以看到,arrayMethods ⾸先继承了 Array,然后对数组中所有能改变数组⾃⾝的⽅法,如 push、pop 等这些⽅法进⾏重写。重写后的⽅法会先执⾏它们本⾝原有的逻辑,并对能增加数组长度的 3 个⽅法 push、unshift、splice ⽅法做了判断,获取到插⼊的值,然后把新添加的值变成⼀个响应式对象,并且再调⽤ ify() ⼿动触发依赖通知,这就很好地解释了
⽤ vm.items.splice(newLength) ⽅法可以检测到变化。。
1. 向响应式的数组或者对象中修改已有的属性的⽅法
vue json字符串转数组当想要修改对象或者属性,并⾮新增属性时,⼀个已经在 data 中声明过的响应式数据,可以直接操作改变,数据改变会经过上图的步骤,触发视图改变。直接 = xxx 即可,数组除外,但是后台传过
来的 json 数组,数组中嵌套的对象也可以直接修改数组中的对象,因为 Object.defindeProperty 的缺陷导致⽆法监听数组的变动,但始终会深度遍历data中数据,给数组中嵌套的对象添加上 get 和 set ⽅法,完成对对象的监听。所以数组中嵌套的对象的情况是可以直接修改数组中的对象,并且保持响应式。
2. 向响应式的数组或者对象中新增⼀个响应式的属性的⽅法this.$set()或者数组变异⽅法
即使是⼀个后台传过来的 json 数组,也可以使⽤this.$set向数组中的其中⼀个对象中添加⼀个响应式的属性,例如 this.$set(arr[0], 'xxx', xxx) 。或者使⽤数组变异⽅法例如splice,更多数组变异⽅法可以参考vue⽂档。
3. data中声明过的数组或者对象,整体替换数组或者对象保持响应式
向响应式的数组和对象替换为新的响应式数据,可直接复制,因为data中声明的数据已经添加了访问器属性setter,当重新赋值⼀个新的堆内存地址时,该数组或者对象也会被循环遍历添加访问器属性,所以也是有响应式的。
4. vue⽆法监听对象的新增和删除,直接通过 = xxx新增⼀个没有的属性,同时修改当前组件的⼀个响应式的数据,会重新触发当前组件重新render,可以让⾮响应式数据也保持更新状态(并⾮响应式)。
给⼀个数据添加⼀个⾮响应式的数据,例如⼀个已经在data中声明过的数据obj,=xxx,新增⼀
个原本没有的数据,同时修改组件中⼀个其他的响应式数据,该obj也会同步更新到最新的数据,另⼀种情况,当你向⼀个对象或者数组中同时增加⼀个响应式和⾮响应式数据,⾮响应式数据也会同步更新到页⾯。
总结:只要触发当前组件重新render,就可以让数据保持更新的状态,例如this.$forceUpdate()。
为什么vue不能监听数组的变化?
Object.defindProperty虽然能够实现双向绑定了,但是还是有缺点,只能对对象的属性进⾏数据劫持,所以会深度遍历整个对象,不管层级有多深,只要数组中嵌套有对象,就能监听到对象的数据变化⽆法监听到数组的变化,Proxy就没有这个问题,可以监听整个对象的数据变化,所以⽤vue3.0会⽤Proxy代替definedProperty。
最后实现⼀个数据双向绑定原理
更深的底层原理还在学习中,完全消化以后会继续分享,嗯,就酱~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论