vue-監聽數組變化


Vue.js觀察數組變化主要通過以下7個方法(push、pop、shift、unshift、splice、sort、reverse)

怎么實現?

通過對data數據中數組的這7個方法進行重新包裝(注意只是data數據中的數組)

為什么不直接對Array.prototype的原型方法進行重新包裝?

因為不應該過多地去影響全局

代碼實現

 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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM