Vue源码探秘之数据响应式原理笔记
第一节课
彻底弄懂Vue2的数据更新原理,手写相关实现代码,让相关知识不再处于“忽悠阶段”
从MVVM模式说
模板:<p>我{{age}}岁了</p>
数据变化:this.age++
数据变了,视图就会跟着变化
model<=>view
侵入式和非侵入式
Vue数据变化 //属于非侵入式
this.a++;
React数据变化 //属于侵入式
this.setState({
a:this.state.a+1;
});
小程序数据变化 //属于侵入式
this.setData({
a:this.data.a+1;
)};
侵入式比如小程序实际上是在setState函数中书写一些语句去改变视图,setState不仅可以改变数据还可以改变视图;非侵入式改变a属性就可以改变视图,这是js赋予的功能,原因是Object.defineProperty()(被称为上帝的钥匙)用来做数据劫持/数据代理,不需要引用任何的包,也不需要任何的插件,从ie8开始兼容,利用js(JavaScript)引擎赋予的功能,检测对象属性的变化,仅有上帝的钥匙还不够,还需要设计一套精密的系统。
第二节课
学习Object.defineProperty()方法
Object.defineProperty()方法会直接在一个对象上定义一个新属性,
或者修改一个对象的现有属性,并返回此对象。
搭建环境
和虚拟DOM和diff算法搭建环境的方法一样
Object.defineProperty()可以设置一些额外的隐藏属性
可以使属性更加自由的被定义
结果
set()函数和get()函数
get()函数和value不能一起在Object.defineProperty()中定义
上图表明相当于把a数据给劫持了,非侵入式
第三节课
defineReactive函数
setter函数仅接受参数赋值给该属性的新值,默认为undefined
getter函数的返回值将被作为该属性的值,默认为undefined
setter函数和getter函数需要变量周转才能正常工作
利用defineReactive函数构造闭包环境,闭包环境具有内外两层嵌套的
val实际上造成了闭包环境,defineReactive()函数实际上相当于替代了临时变量(节省了设置临时变量)
第四节课
递归侦测对象全部属性
第五节课
以上三张图片循环调用
observe.js->Observer.js->defineReactive.js->observe.js
机制负荷下图规则
结果
第六节课
数组响应式原理
改写七种方法push pop shift unshift splice sort reverse
所有Array打点就能调用的方法都是来自于Array.prototype这个对象
Object.setPrototypeOf(o,arrayMethods)和o.prototypeOf=arrayMethods相等
Vue当中数组的响应式是如何实现的?
以Array.prototype为原型创建arrayMethods对象,
ES6提供了一个强制的方法Object.setPrototypeOf()
将数组的proto强制指向arrayMethods
第七节课
第八节课
依赖收集
需要用到数据的地方,称为依赖。
Vue1.x,细粒度依赖,用到数据都是依赖;
Vue2.x,中等粒度依赖,用到数据的组件都是依赖;
在getter方法中收集依赖,在setter方法中触发依赖
依赖就是Watcher,只有Watcher触发的getter才会收集依赖,哪个Watcher触发了
getter,就把哪个Watcher收集到Dep中。
Dep使用发布订阅模式,当数据发生变化时,会循环依赖列表,把所有的Watcher都通知一遍。
代码实现的巧妙之处:Watcher把自己设置到全局的一个指定位置,然后读取数据,因为读取了数据,
所以会触发这个数据的getter,在getter中就能得到当前正在读取数据的Watcher,并把这个Watcher
收集到Dep中。