Vue
# 思路
new Vue()
首先执行初始化,对data
执行响应化处理,这个过程发生在Observer
中- 同时对模板执行编译,找到其中动态绑定的数据,从
data
中获取并初始化视图,这个过程发生在compile
中 - 同时定义一个 更新函数 和
Watcher
,将来对应数据变化时Watcher
会调用 更新函数 - 由于
data
的某个key
在视图中可以出现多次,所以每个key
都需要一个管家Dep
来管理多个Watcher
- 将来
data
中的数据一旦发生变化,会首先找到对应的Dep
,通知所有Watcher
执行更新函数
职责划分
- CVue:框架构造函数
- Observer:执行数据响应化(分辨数据是对象还是数组)
- Compile:编译模板,初始化视图,收集依赖(更新函数、watcher 创建)
- Watcher:执行更新函数(更新 DOM )
- Dep:管理多个 Watcher,批量更新
# 实现
- 响应化处理及数据代理
// cvue.js
class CVue {
constructor(options) {
// 保存选项
this.$options = options;
this.$data = options.data;
// 响应化处理
observe(this.$data);
// 代理
Proxy(this, '$data')
}
}
// 代理函数,提供对$data中数据的直接访问
function Proxy(vm, sourceKey) {
Object.keys(vm[sourceKey]).forEach(key => {
Object.defineProperty(vm, key, {
get() {
return vm[sourceKey][key];
},
set(newVal) {
vm[sourceKey][key] = newVal;
}
})
})
}
function defineReactive(obj, key, val) {
// 递归
observe(val);
// 对传入obj进行访问拦截
Object.defineProperty(obj, key, {
get() {
console.log('get ' + key);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log('set ' + key + ':' + newVal);
// 如果传入的newVal依然是obj,需要做响应化处理
observe(newVal);