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);
相關文章
相關標籤/搜索