vue知识点-2--$watch、$set、$delete内部原理

本文相当于笔记,最近在看深入浅出vue.js的记录,需要配合书一起看,如果你也在看这本书可以一起看看这篇文章,不然会看不懂。

$watch

$watch('需要监测的数据', '数据变化后出发的回调', 'depp | immediate');
第一个参数可以是个字符串或是函数 需要监测的数据
第二个参数是函数 鼠标变换时的回调函数,会传入new val 和 old val
第三个参数是对象
deep 该对象下的子数据变化是否触发回调
immediate 是否立即触发一次回调

$watch 返回的 是 unwatch 运行后会取消观察函数

这些$的方法都是挂在了vue 的原型上

Vue.prototype.$watch = function(expOrFn,cb,options){
  const vm = this;
  const watcher = new Watcher(vm,expOrFn,cb,options)
  ....其他代码
}

多的就不打了 我也是一个个敲的比较累。
在原型上的 watch 会 把this赋值成vm 并且传递进Watcher 得到他的实例-->wather
然后判断是否有immediate
如果有立即用 call保持上下文 运行一次回调换算
然后再返回 wather.teardown 是个函数就是可以销毁当前watch的函数

现在把重点放在 Watcher 里面 上一篇文章介绍过 Watcher 现在还需要补充一下
Watcher中 有 get() 获取数据的 update()更新数据的 里面是用call保持上下文关系执行的回调函数,现在watch第一个参数可能是个函数,现在需要实现的功能就是函数中使用的数据变换时都要来更新,
如果是个函数 比如 传递的是 function(){ return this.a + this.b }
数据变化时的回调就是 最新的return结果 和上次的return的结果
记录了多个值 Watcher 和 dep 的关系就是多对多的关系,Watcher 中也要有数据记录自己触发了哪些数据,然后在销毁当前监听时循环遍历出这些数据依次取消监测。
Watcher中新加deps=[] depIds=new set()
新增addDep的方法 这里改动很大,之前是再get赋值window.target 在dep的depend中 把 window.target 加入到subs中
现在改为
addDep接受dep参数 把dep加入 deps 和 id 加入 depIds中,depIds用has()做去重最后调用dep.addsub(this)把自己加入到dep的subs中
dep的depend方法改为window.target.addEep(this)
他们的联系变得更紧密了
Watcher 的 teardown() 是循环自己的deps数组调用每一个的 removeSub 让对应的dep在自己的subs中把该Watcher删除掉
每个dep有removeSub方法 接受sub 也就是 watch 用indexOf找到位置 用splice 删除。
如果deep存在处理的也不繁琐,循环下 value下面的数据 判断如果不是数组不是对象就返回
然后就是循环去读取一下这个值 就是纯纯的读取一下,因为上面的已经写好了,只要读取一下 dep就会把这个watch加入到subs中 watch也会把这个dep加入到自己的deps数组中。

$set

第一个参数 数组或是对象
第二个参数 key 或是 index
第三个参数 value 设置的值
处理的也不复杂
如果传入的数组, 就利用splice 把index 的位置 替换成 value
不能直接[index] = value 替换 之前说过 vue 重写了 数组__propto__
调用splice会触发监听并且把新的值变为响应式的

用in 判断 key 是否存在于对象 如果存在说明是响应式的 直接赋值即可触发监测

这些都不是就找到 target(第一个参数)的__ob__
判断target 不是vue实例 不是根数据 有一个是的就报错返回

如果target没有ob 证明不是响应式的 就直接赋值即可
如果是响应式的 存在ob 调用definereacter 然后再调用下ob.dep.notify();

你可能感兴趣的:(vue知识点-2--$watch、$set、$delete内部原理)