美文网首页
Vue 响应式注意事项

Vue 响应式注意事项

作者: _1633_ | 来源:发表于2020-12-05 23:30 被阅读0次

    对象添加属性

        在项目初始化过程中,如果没有在 data 中初始化 一个属性,那么如果在后面的过程中直接给这个属性赋值,是不会触发它的 setter, 因为在 initData 过程中并没有给它进行响应式。

        为了解决这个问题,Vue 定义了一个全局的方法, Vue.set

set

    set 方法接收 3个参数, target 可能是数组或者是普通对象, key 代表的是数组的下标或者是对象的键值, val 代表添加的值。

    ⾸先判断如果 target 是 数组 且 key 是⼀个合法的下标,则之前 通过 splice 去添加进数组然后返回,这里的 splice 其实已经不仅仅是原⽣数组的 splice 了(看下面数组注意事项);

    接着又判断 key 已经存在于 target 中,则直接赋值返回,因为这样的变化是可以观测到了。    

    接着再获取到 target.__ob__ 并赋值给 ob ,它是在 Observer 的构造函数执行的时候初始化的,表示 Observer 的一个实例,如果它不存在,则说明 target 不是一个响应式的对象,则直接赋值并返回。

    最后通过 defineReactive(ob.value, key, val) 把新添加的属性变成响应式对象,然后再通过 ob.dep.notify() 手动的触发依赖通知

getter

     defineReactive 过程中 对新值val  递归调用  observe 方法,这样就保证了无论  val 的结构多复杂,它的所有子属性也能变成响式的对象,这样我们访问或修改 val 中⼀个嵌套较深的属性,也能触发 getter 和 setter。  在 getter 过程中判断了 childOb ,并调用了 childOb.dep.depend() 收集了依赖,Vue.set 的时候通过 ob.dep.notify() 能够通知到 watcher (ob 就是 target.__ob__, 也就是 target 的  observe 实例 ,target 原本就是响应式, 它的 dep 中 存放了所有的 watcher),让添加新的属性到对象也可以检测到变化,如果 value 是个数组,那么就通过 dependArray 把数组每个元素也去做依赖收集。


    数组注意事项

        Vue 不能检查到以下变动的数组

            1. 利用索引直接设置数组的一项,vm.item[ index ] = value;

            2. 修改数组的长度, vm.item.length = length;

        对于第一种情况,可以使用 Vue.set(item, indexOfitem,value);

        对于第二章情况,可以使用 vm.item.splice(length)

        Vue 通过 observe 方法去观察对象的时候会实例化 Observer,这个过程中堆数组进行了专门的处理

Observer

        value 为数组,那么 首先 hasProto 判断是否 支持 __protp__

            export const hasProto = '__proto__' in {}

        如果支持, protoAugment 处理; 否则 copyAugment 处理:

处理方式

        arrayMethods 是什么呢

        对于 7 中操作数组的方法,我们 对它进行了功能的扩充:arrayMethods ⾸先继承了 Array ,然后对数组中所有能改变数组自⾝的方法, 对这 7中方法 进行重写。

        重写后的⽅法会先执⾏它们本⾝原有的逻辑,并对能增加数组长度的 3 个方法 push、unshift、splice ⽅法做了判断,获取到插如的值(也就是对新值进行响应式),然后把新添加的值变成⼀个响应式对象,并且再调⽤ ob.dep.notify() 手动触发依赖通知。

arrayMethods

    回到 protoAugment,protoAugment 方法是直接把 target.__proto__ 原型直接修改为 src ,而 copyAugment ⽅法是遍历 keys,通过 def ,也就是 Object.defineProperty 去定义它⾃⾝的属性值。对于大部分现代浏览器都会走 protoAugment 这个逻辑 ,实际上就把 value 的原型指向了 arrayMethods 这个我们重写的原型上。

    然后 执行 this.observeArray(value), 对 数组的每一项进行 observe, 也就是深度劫持。

相关文章

网友评论

      本文标题:Vue 响应式注意事项

      本文链接:https://www.haomeiwen.com/subject/gdqesktx.html