vue-监听数组变化

Vue.js观察数组变化主要经过如下7个方法(push、pop、shift、unshift、splice、sort、reverse)数组

怎么实现?浏览器

经过对data数据中数组的这7个方法进行从新包装(注意只是data数据中的数组)缓存

为何不直接对Array.prototype的原型方法进行从新包装?app

由于不该该过多地去影响全局工具

代码实现测试

 1 const patchArray = (function () {  2     const methodsToPatch = [  3         'push',  4         'pop',  5         'shift',  6         'unshift',  7         'splice',  8         'reverse',  9         'sort'
10  ]; 11 
12 //设置对象属性的工具方法
13     function def (obj, key, val) { 14  Object.defineProperty(obj, key, { 15  value: val, 16             enumerable: true, 17             writable: true, 18             configurable: true
19  }); 20  } 21 
22     const arrayProto = Array.prototype, //缓存Array的原型
23         arrayMethods = Object.create(arrayProto); //继承Array的原型
24 
25     methodsToPatch.forEach(function (method, index) { 26         def(arrayMethods, method, function (...args) { 27             //首先调用Array原型的方法
28             const res = arrayProto[method].apply(this, args); 29             //data中每一个数组都有一个__ob__的私有属性指向建立的Observer实例(有兴趣看看源码中的observe方法,这里不详述)
30             const ob = this.__ob__; 31 
32             let inserted = null; 33 
34             //记录插入的值
35             switch(method) { 36                 case 'push': 37                 case 'unshift': 38                     inserted = args; 39                     break; 40                 case 'splice': 41                     inserted = args.slice(2); 42                     break; 43  } 44 
45             if (inserted) { 46                 //若是是调用了push、unshift、splice,则尝试对新插入的值进行响应式绑定,由于插入的值有多是对象(Object)或者数组(Array)
47                 ob && ob.observeArray(inserted); 48  } 49 
50             console.log('数组发生改变了'); 51 
52             //向全部依赖发送通知,告诉它们数组的值发生变化了
53             ob && ob.dep.notify(); 54             return res; 55  }); 56  }); 57 
58     return function (target) { 59         //看看浏览器支不支持__proto__这个属性,经过改变__proto__的值,能够设置对象的原型
60         if ('__proto__' in {}) { 61             //将数组的原型指向arrayMethods,这样当数组调用上述的7个方法时,实际上是调用arrayMethods中的方法而不是调用Array.prototype中的方法
62             target.__proto__ = arrayMethods; 63         } else { 64             //若是浏览器不支持__proto__,则设置数组对应的属性,这样当数组调用上述的7个方法时,实际上是调用数组对应属性指向的方法
65             for (let i = 0, l = methodsToPatch.length; i < l; i++) { 66                 let key = methodsToPatch[i]; 67  def(target, key, arrayMethods[key]); 68  } 69  } 70  } 71 })(); 72 
73 //测试
74 let arr = [1, 2, 3]; 75 patchArray(arr); 76 arr.push(4);
相关文章
相关标签/搜索