Vue.js response principle

Keywords: Vue

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

Posted by oavs on Mon, 07 Oct 2019 05:06:45 -0700