概括
watch就是观测数据的变化,这个数据可以是data中的,也可以是computed中的。
流程
初始化与建立联系
watch的初始化也是在initState中,在initWatch中开始。首先,wacth的属性可以是数组,如果是数组的话,就遍历数组,然后对每个数组中的元素调用createWatcher方法。如果不是数组,就直接调用createWatcher方法。
createWatcher会对观测数据的值的不同做不同处理。如果观测数据的值是字符串,就从vue实例上获取函数;如果是函数,那么直接就是 监听回调;如果配置是个对象,就取handler字段。
然后就调用vm.watch函数中,会对每个watch实例化一个watcher对象。watcher中会传入四个参数,watcher实例的第一个参数,是当前vue实例对象,第二个参数是watch属性的key,是在watcher实例中get方法中用到。第三个参数是watch属性表达式对应的方法,是观测到数据变化后的回调函数。第四个参数就是一些配置项。当创建实例时,会根据第四个参数的值给watcher.user赋值true,证明这个watcher是用户自己创建的。然后watcher.cb设置第三个参数,紧接着是设置watcher.getter的值,这个值其实是第二个参数,也就是当前所处理的watch属性的key,因为这个key是个字符串,所以watcher会对它进行下处理,让它变为一个函数,这个函数就是返回入参上,这个key的值。
紧接着是调用watcher.get()方法,把当前观测的属性的watcher实例赋值给Dep.targte。然后调用实例上的getter方法,用call的形式调用,参数是vm即vue实例。这时返回的就是vm上的属性的值。在获取vm上的属性值时,由于这个属性值时相应式的,必定会触发其get方法,这样就会把当前watch的watcher收集起来。如果用户设置了deep属性要深度观测,那么就遍历获取当前属性里的对象或数组中的值,因为这些值也是响应式的,也会收集起当前watch的watcher。这样就完成了watch和观测数据的联系。然后把Dep.target还原回原来的值。如果用户设置了immediate,表明要立即返回值,那么直接把刚才从vm上获取的值返回即可。
通知更新
在所观测的数据发生变化时,数据的set方法会调用其dep的notify方法,通知依赖更新。这时,watch的watcher就会调用update方法,update在经历完异步调用后会调用watcher.run()方法,run方法会调用watcher.get()方法获取下当前最新的值,然后run方法里会判断watcher.user是否为true,为true的化就会调用watcher.cb方法,也就是watch对应的方法,把之前观测属性的值和刚通过get方法获取到的属性的最新值作为参数传给watcher.cb。
以上整个流程结束。