vue源码中的observer运作

observer: 其主要目的就是对每条数据进行观察和劫持。我们可以在一下源码中可以看到相应的操作:

function Observer(obj) {
    this.data = obj;//暂存data数据,方便以后的操作
    this.walk(obj);//对所有属性进行遍历
}

Observer.prototype = {
    walk: function(obj) {
        var that = this;//暂存实例
        Object.keys(obj).forEach(function(key) { //对data里所有的属性名进行遍历
            that.convert(key, obj[key]);
        });
    },
    //为每个属性增加响应式
    convert: function(key, val) {
        //响应式=> defineReactive
        this.defineReactive(this.data, key, val);
    },

    defineReactive: function(obj, key, val) {
        //为data中所有层次的属性都创建一个dep实例
        var dep = new Dep();
        //递归遍历data中所有层次的属性
        var childObj = observe(obj);

        //(Object.defineProperty数据劫持),新增get和set方法
        Object.defineProperty(obj, key, {//obj为此对象,key为新增或修改的属性,后面的{}内的描述就是属性描述
        	configurable: false, // 不可配置
            enumerable: true, // 可枚举
            get: function() {
                //判断当前Dep.target的watcher是否存在
                if (Dep.target) {//Dep.target上存放这当前需要操作的Watcher实例,调用depend会调用该Watcher实例的方法
                    dep.depend();
                }
                return val;
            },
            set: function(newVal) {
                if (newVal === val) {//如果新增数据和原有数据一样就终止运行
                    return;
                }
                //反之,就让observe对新增的数据进行劫持
                val = newVal;//新值覆盖原有的值
                childObj = observe(newVal);
                dep.notify();//Dep是Observer与Watcher的纽带,当数据变化时,会被Observer观察到,然后由Dep通知到Watcher
            }
        });
    }
};
//新建队列,重新观察
function observe(val, vm) {
    //判断val是否存在 或者val数据类型是否为对象
    if (!val || typeof val !== 'object') {
        return;
    }
    return new Observer(val);
};

上一篇:vue双向数据绑定原理


下一篇:观察者模式封装