vue简版源码 Observer

vue简版源码 Observer篇

相关链接:MVVM篇Compile篇Watcher篇

这篇代码的入口在中间 function observe(value, vm) 的时候。

function Observer(data) {
    //在Observer实例上暂存data
    this.data = data;
    // 调用Observer 里 walk 方法 ,这里用的是颗粒化开发思想
    this.walk(data);
}

Observer.prototype = {
    walk: function(data) {
        var me = this; // 暂存this 保证this的指向正确  这里的this是 Observer 实例 
        //对data里所有的属性名进行遍历
        Object.keys(data).forEach(function(key) {
            // 调用Observer 里 convert方法 ,这里用的是颗粒化开发思想
            me.convert(key, data[key]);  // 参数一:每一项属性名 , 参数二:data中每一项的属性值
        });
    },
    convert: function(key, val) {
        // 为每个属性增加响应式 
        // 参数一:说到底还是传递过来的那个data对象,一直没变 , 
        // 参数二:每一项的属性名
        // 参数三:每一项的属性值 可能是值类型,也可能是对象的形式 
        this.defineReactive(this.data, key, val);
    },

    defineReactive: function(data, key, val) {
        //为data中所有层次的属性都创建一个dep实例 
        var dep = new Dep();
        // 递归遍历data中所有层次的属性
        // 这就是我在上面说的参数三,可能是对象形式,大家可以去下面看一下递归的终止条件 直到它不是存在并且不是object类型
        var childObj = observe(val);  

        // 为原有属性新增get和set方法(数据劫持) 
        Object.defineProperty(data, key, {
            enumerable: true, // 可枚举
            configurable: false, // 不能再define
            get: function() {
                // 在写操作的时候如果有订阅者,调用depend 方法
                if (Dep.target) {
                    dep.depend();
                }
                return val;
            },
            set: function(newVal) {
                if (newVal === val) {
                    return;
                }
                val = newVal;
                // 新的值是object的话,进行监听
                childObj = observe(newVal);
                // 通知订阅者
                dep.notify();
            }
        });
    }
};

	// 入口
function observe(value, vm) {
    //判断value是否存在或者value的数据类型是否为object(递归的终止条件)
    if (!value || typeof value !== 'object') {
        return;
    }

    return new Observer(value);
};


var uid = 0;

function Dep() { // 构造函数 挂载在 window 上
    //没创建一个dep都会给这个dep增加一个独立的标识
    this.id = uid++; // 从0开始
    this.subs = []; // 存放订阅者的容器 watcher 
}

Dep.prototype = {
    // 在 订阅者上 watcher 触发
    addSub: function(sub) {  // sub : 订阅者 watcher
        this.subs.push(sub); // 存放订阅者 watcher
    },

    depend: function() {
        // Dep.target :是订阅者 watcher  调用 watcher 里 addDep 方法,参数this是Dep 本身
        Dep.target.addDep(this);
    },

    removeSub: function(sub) {
        var index = this.subs.indexOf(sub);
        if (index != -1) {
            this.subs.splice(index, 1);
        }
    },

    //通知所有的watcher
    notify: function() {
        //遍历subs中所有的 watcher 的实例
        this.subs.forEach(function(sub) {
            // 每一个watcher的实例调用update方法
            sub.update();
        });
    }
};
// 重点!!不能忘 在Dep构造函数上定义的属性,目前是null,在 watcher.js 中用的到  
// 构造函数 挂载在window 上 在哪都能调用!!!
Dep.target = null;  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值