DMQ / mvvm

剖析vue实现原理,自己动手实现mvvm

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Watcher存在的问题

bravepg opened this issue · comments

多谢提供的分享,但是Watcher存在一个问题

function Watcher(vm, exp, cb) {
    this.cb = cb;
    this.vm = vm;
    this.exp = exp;
    // 此处为了触发属性的getter,从而在dep添加自己,结合Observer更易理解
    this.value = this.get(); 
}
Watcher.prototype = {
    update: function() {
        this.run();	// 属性值变化收到通知
    },
    run: function() {
        var value = this.get(); // 取到最新值
        var oldVal = this.value;
        if (value !== oldVal) {
            this.value = value;
            this.cb.call(this.vm, value, oldVal); // 执行Compile中绑定的回调,更新视图
        }
    },
    get: function() {
        Dep.target = this;	// 将当前订阅者指向自己
        var value = this.vm[exp];	// 触发getter,添加自己到属性订阅器中
        Dep.target = null;	// 添加完毕,重置
        return value;
    }
};

如果每次触发更新,都会把Watcher加入观察者中,存在部分性能问题
可以这样

function Watcher(vm, exp, cb) {
    Dep.target = this;	// 将当前订阅者指向自己
    this.cb = cb;
    this.vm = vm;
    this.exp = exp;
    // 此处为了触发属性的getter,从而在dep添加自己,结合Observer更易理解
    this.value = this.get(); 
    Dep.target = null;	// 添加完毕,重置
}
Watcher.prototype = {
    update: function() {
        this.run();	// 属性值变化收到通知
    },
    run: function() {
        var value = this.get(); // 取到最新值
        var oldVal = this.value;
        if (value !== oldVal) {
            this.value = value;
            this.cb.call(this.vm, value, oldVal); // 执行Compile中绑定的回调,更新视图
        }
    },
    get: function() {
        var value = this.vm[exp];	// 触发getter,添加自己到属性订阅器中
        return value;
    }
};

只有每次初始化的时候才会加入观察者

commented

addDep的时候做了去重处理的,不会有问题,你这样处理反而会导致某些场景下添加不了订阅者,见:watcher.js addDep函数低第4点注释