Vue.js 响应式原理

时间:2020-12-18 18:23:33

1. Vue2.x 基于 Object.defineProperty 方法实现响应式(Vue3 将采用 Proxy)

Object.defineProperty(obj, prop, descriptor)

### 2. 定义 defineReactive 来对对象的属性进行 getter、setter 操作
```js
function defineReacive(obj, key, val){
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
return val;
},
set(newVal) {
if(val === newVal) return;
val = newVal;
callback(newVal);
}
})
}
```

### 3. 我们需要遍历所有数据,所以需要 observer 方法去观察
```js
function observer(val){
if(!val || typeof val !== 'object') return;
Obejct.keys(val).forEach(key => {
defineReactive(val, key, val(key));
})
}
```

### 4. 模拟 Vue 构造函数
```js
class MockVue {
constructor(options) {
this._data = opations.data;
observer(this._data);
}
}
```

### 5. 实例化 MockVue 生成实例对象
```js
let v1 = new MockVue({
data: { }
})
```

## 如何让发生变动时触发相关视图更新,那么我们就需要收集依赖,

### 6. 订阅者 Dep(存放watcher观察者对象)
```js
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => {
sub.update();
})
}
}
```

### 7. 观察者 Wacher
```js
class Watcher {
constructor() {
Dep.target = this;
}
update() {
console.log('update...');
}
}
```

### 8. 修改 defineReactive 方法
```js
function defineReacive(obj, key, val){
+ const dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
+ dep.addSub(Dep.target);
return val;
},
set(newVal) {
if(val === newVal) return;
val = newVal;
- callback(newVal);
+ dep.notify();
}
})
}
```

### 9. 重写 MockVue
```js
class MockVue {
constructor(options) {
this._data = options.data;
observer(this._data);
new Watcher(); // Dep.target会指向这个watcher对象
console.log('触发getter');
}
}
```