重读vue的MVVM

293 阅读1分钟

vue双向数据绑定

watcher怎么链接observe和compile?

observe

* a.通过Object.defineProperty属性拿到数据的getter和setter方法;[存取器]。
对象的属性有任何赋值都会促发get方法。 发出一个消息, 订阅这个消息订阅者促发回掉;
* b.为所有数据添加监听器dep。

getter方法的时候,判断存不存在dep.target,如果存在,就将dep.target添加到dep.addsub;
setter方法的时候,调用dep.notify(),遍历dep里面的订阅者,并且执行update方法; 消息订阅器

export default class Dep {
        constructor() {
            this.subs = [];
        };
        addSub(sub) {
            this.subs.push(sub);
        };
        notify() {
            this.subs.forEach(sub => sub.update());
        }
}

watch:

Dep.target = this; // 将当前订阅者指向自己
var value = this.vm[exp]; //
触发getter,添加自己到属性订阅器中
Dep.target = null; // 添加完毕,重置
return value; 代码:
export default class Watcher {
    constructor(vm, expOrFn, cb) {
        this.cb = cb
        this.vm = vm
            //此处简化.要区分fuction还是expression,只考虑最简单的expression
        this.expOrFn = expOrFn
        this.value = this.get()
    }
    update() {
        this.run()
    }
    run() {
        const value = this.get()
        if (value !== this.value) {
            this.value = value
            this.cb.call(this.vm)
        }
    }
    get() {
        Dep.target = this
            //此处简化。。要区分fuction还是expression
        const value = this.vm._data[this.expOrFn]
        Dep.target = null
        return value
    }
}

compile

主要做的事情是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图,如图所示:

监听数据、绑定更新函数的处理是在compileUtil.bind()这个方法中,通过new Watcher()添加回调来接收数据变化的通知