看过vue源码的都知道,vue中通过对data中的属性值进行监听实现了当数据变化时更新视图,其实实现的理论基础是比较简单的,只是结合到整个vue的组件化过程中后便变的贼秀。话不多说,直接撸理论基础
Object.defineProperty,该api提供了对对象属性读写的更精确的控制,其对obj.a以及obj.a=newValue进行了操作前拦截。其参数三作为配置对象提供了对对象读写权限的修改控制方式,配置下的get和set方法则允许我们在操作前做一些额外的事情
实现
像vue一样,我们也把data代理到实例上一份,可以直接在实例上访问
对data进行遍历,这显然应当是一次递归过程,由于Object.defineProperty只支持对象形式,故对于基本数据类型,即是该递归的出口。同时由于代理到实例的_data和data指向同一引用,故通过实例对_data的操作能够触发data的响应式操作
框红的地方主要是为了避免死循环,利用闭包修改外部变量,配合get达到肉眼修改的目的(其实只是获取的时候取得是外部缓存的值,实际上内部有没有修改?I don't know)
既然已经对data中的每一层属性操作都架设了拦截,那么只需要在合适的时机收集依赖,在一定的条件下触发更新即可。那收集谁?收集到哪里?这里和vue一样,使用dep类收集watcher,至于watcher具体要干什么我不关心
定义Watch类和Dep类,Watch类作为客户端,去执行具体的动作,Dep类则作为广播工具,适时通知到Watch。那么如何建立二者之间的关系呢?
最后,在get时调用depend,该方法传入dep并调用watch的addDep方法,即将dep保存到watcher实例又将watcher示例绑定到dep中,这样就完成了依赖收集(即:将watcher收集到dep中)。之后只需要在设置属性时调用notify通知watcher作更新即可