Array的变化侦测(二)

侦测数组中元素变化

侦测数组的变化类比对Object的递归处理,我们也需要监测子项的变化。
另外,数组与对象的使用需求有些不同,数组要求新增的项依然能够被监测到(想象你对一个响应式的数组push一个子数组,后面操作这个子数组时,页面没反应,就显得奇怪了!)
首先做对子项的侦测:

export class Observer{
    constructor(value){
        this.value = value;
        def(value, '__ob__', this);
        if(Array.isArray(value)){
            this.observeArray(value);
        } else {
            this.walk(value);
        }
    }
    observeArray(items){
        for(let i = 0, l = keys.length;i < l;i++){
            observe(items[i]);
        }
    }
}

像这样对数组进行递归的处理就可以做到子项变成响应式的了。

侦测新增元素的变化
[
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sorte',
    'reverse'
].forEach(function(method){
    const original = arrayProto[method];
    def(arrayMethods, method, function mutator(...args){
            const ob = this.__ob__;
            let inserted;
            switch(method){
                case 'push':
                case 'unshift':
                    inserted = args;
                    break;
                case 'splice':
                    inserted = args.slice(2);
                    break;
            }
            ob.dep.notify();
            return original.apply(this, args);
        })
})

不难发现九个方法中,可以新增元素的只有前插、后插和插入操作,捕捉响应的参数就好了。
获取的到新增元素的话就可以递归的把这些变成响应式数据了。

[
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sorte',
    'reverse'
].forEach(function(method){
    const original = arrayProto[method];
    def(arrayMethods, method, function mutator(...args){
            const ob = this.__ob__;
            let inserted;
            switch(method){
                case 'push':
                case 'unshift':
                    inserted = args;
                    break;
                case 'splice':
                    inserted = args.slice(2);
                    break;
            }
            if(inserted) ob.observeArray(inserted); // 新增
            ob.dep.notify();
            return original.apply(this, args);
        })
})
侦测数组的缺陷

由于是通过拦截原型方法完成响应,因此,对于通过[]直接修改和对length的赋值无法侦测。

this.list[0] = 2;
this.list.length = 0;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,282评论 0 4
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,441评论 0 3
  • 深入浅出 - vue变化侦测原理 关于vue的内部原理其实有很多个重要的部分,变化侦测,模板编译,virtualD...
    如烟灬阅读 282评论 0 1
  • HTML 5 HTML5概述 因特网上的信息是以网页的形式展示给用户的,因此网页是网络信息传递的载体。网页文件是用...
    阿啊阿吖丁阅读 4,198评论 0 0
  • 仰望清空,朵朵黑云镶嵌着银色的光晕。 回想着一幕幕的过往云烟,心死! 我错了吗?一遍遍的问...
    蟲_53b8阅读 272评论 2 0