MVVM
- M:模型(Model),对应data中的数据
- V:视图(View),模板
- VM:视图模型(ViewModel),Vue实例对象
- data中所有的属性,都会在vm上
- vm上所有的属性及Vue原型上所有属性,在Vue模板中都可直接使用
侵入式与非侵入式
数据劫持/数据代理
利用JavaScript引擎赋予的功能,检测对象属性变化
- Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。可配置属性:
1.属性描述符- writable:是否可写
- enumerable:是否可枚举
- configurable:是否能被删除
2.存取描述符 - get:读取obj的p属性时,调用getter,返回值即p的值
- set:修改obj的p属性时,调用setter,可得到修改后的值
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
defineReactive函数
封装Object.defineProperty()方法,动态存取属性
function defineReactive(obj, prop, attr) {
Object.defineProperty(obj, prop, {
//可枚举
enumerable: true,
//可被删除
configurable: true,
//getter
get() {
console.log('------',
prop);
return attr;
},
//setter
set(newAttr) {
console.log('=======',
prop, newAttr);
if (attr === newAttr) return;
attr = newAttr;
}
})
};
递归侦测对象全部属性
数组响应式
重写数组的7种方法
- push
- pop
- shift
- unshift
- splice
- reverse
- sort
原理:以Array.prototype为原型,创建了一个arrayMethods的对象,利用Object.setPrototypeOf或者o._proto_,使数组的原型链指向arrayMethods,因此可以调用重写的方法
依赖收集
依赖
需要用到数据的地方,称为依赖
- vue1.x 细粒度依赖,用到数据的DOM都是依赖
- vue2.x 中等粒度依赖,用到数据的组件是依赖
- 在getter中收集依赖,在setter中触发依赖
Dep类和Watcher类
- 将依赖收集的代码封装成一个dep类,专门用来管理依赖,每个Observer的实例,成员中都有一个Dep的实例
- Watcher是一个中介,数据发生变化时通过Watcher中转,通知组件
手写源码地址