Links to the original text: http://www.cnblogs.com/colima/p/10508913.html
1. Vue2.x implements response based on Object.defineProperty (Vue3 will adopt Proxy)
Object.defineProperty(obj, prop, descriptor)
2. Define defineReactive to getter and setter the attributes of an object
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. We need to traverse all the data, so we need observer method to observe.
function observer(val){ if(!val || typeof val !== 'object') return; Obejct.keys(val).forEach(key => { defineReactive(val, key, val(key)); }) }
4. Simulated Vue constructor
class MockVue { constructor(options) { this._data = opations.data; observer(this._data); } }
5. Instantiating MockVue to Generate Instance Objects
let v1 = new MockVue({ data: { } })
How to trigger related view updates when changes occur, then we need to collect dependencies.
6. Subscriber Dep (storing watcher observer objects)
class Dep { constructor() { this.subs = []; } addSub(sub) { this.subs.push(sub); } notify() { this.subs.forEach(sub => { sub.update(); }) } }
7. Wacher the Observer
class Watcher { constructor() { Dep.target = this; } update() { console.log('update...'); } }
8. Modify DefneReactive Method
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. Rewrite MockVue
class MockVue { constructor(options) { this._data = options.data; observer(this._data); new Watcher(); // Dep.target points to the watcher object console.log('trigger getter'); } }
Reprinted at: https://www.cnblogs.com/colima/p/10508913.html