• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    vue源碼學習之Object.defineProperty 對數組監聽

    來源:懂視網 責編:小采 時間:2020-11-27 22:13:47
    文檔

    vue源碼學習之Object.defineProperty 對數組監聽

    vue源碼學習之Object.defineProperty 對數組監聽:上一篇中,我們介紹了一下defineProperty 對對象的監聽,這一篇我們看下defineProperty 對數組的監聽 數組的變化 先讓我們了解下Object.defineProperty()對數組變化的跟蹤情況: var a={}; bValue=1; Object.defineProper
    推薦度:
    導讀vue源碼學習之Object.defineProperty 對數組監聽:上一篇中,我們介紹了一下defineProperty 對對象的監聽,這一篇我們看下defineProperty 對數組的監聽 數組的變化 先讓我們了解下Object.defineProperty()對數組變化的跟蹤情況: var a={}; bValue=1; Object.defineProper

    上一篇中,我們介紹了一下defineProperty 對對象的監聽,這一篇我們看下defineProperty 對數組的監聽

    數組的變化

    先讓我們了解下Object.defineProperty()對數組變化的跟蹤情況:

    var a={};
    bValue=1;
    Object.defineProperty(a,"b",{
     set:function(value){
     bValue=value;
     console.log("setted");
     },
     get:function(){
     return bValue;
     }
    });
    a.b;//1
    a.b=[];//setted
    a.b=[1,2,3];//setted
    a.b[1]=10;//無
    輸出 a.b.push(4);//無輸出 a.b.length=5;//無輸出 a.b;//[1,10,3,4,undefined];

    可以看到,當a.b被設置為數組后,只要不是重新賦值一個新的數組對象,任何對數組內部的修改都不會觸發setter方法的執行。這一點非常重要,因為基于Object.defineProperty()方法的現代前端框架實現的數據雙向綁定也同樣無法識別這樣的數組變化。因此第一點,如果想要觸發數據雙向綁定,我們不要使用arr[1]=newValue;這樣的語句來實現;第二點,框架也提供了許多方法來實現數組的雙向綁定。

    對于框架如何實現數組變化的監測,大多數情況下,框架會重寫Array.prototype.push方法,并生成一個新的數組賦值給數據,這樣數據雙向綁定就會觸發。

    實現簡單的對數組的變化的監聽

    var arrayPush = {};
    (function(method){
     var original = Array.prototype[method];
     arrayPush[method] = function() {
     // this 指向可通過下面的測試看出
     console.log(this);
     return original.apply(this, arguments)
     };
    })('push');
    
    var testPush = [];
    testPush.__proto__ = arrayPush;
    // 通過
    輸出,可以看出上面所述 this 指向的是 testPush // [] testPush.push(1); // [1] testPush.push(2);

    在官方文檔,所需監視的只有 push()、pop()、shift()、unshift()、splice()、sort()、reverse() 7 種方法。我們可以遍歷一下:

    var arrayProto = Array.prototype
    var arrayMethods = Object.create(arrayProto)
    
    ;[
     'push',
     'pop',
     'shift',
     'unshift',
     'splice',
     'sort',
     'reverse'
    ].forEach(function(item){
     Object.defineProperty(arrayMethods,item,{
     value:function mutator(){
     //緩存原生方法,之后調用
     console.log('array被訪問');
     var original = arrayProto[item] 
     var args = Array.from(arguments)
     original.apply(this,args)
     // console.log(this);
     },
     })
    })

    完整代碼

    function Observer(data){
     this.data = data;
     this.walk(data);
    }
    
    var p = Observer.prototype;
    var arrayProto = Array.prototype
    var arrayMethods = Object.create(arrayProto)
    
    ;[
     'push',
     'pop',
     'shift',
     'unshift',
     'splice',
     'sort',
     'reverse'
    ].forEach(function(item){
     Object.defineProperty(arrayMethods,item,{
     value:function mutator(){
     //緩存原生方法,之后調用
     console.log('array被訪問');
     var original = arrayProto[item] 
     var args = Array.from(arguments)
     original.apply(this,args)
     // console.log(this);
     },
     })
    })
    
    p.walk = function(obj){
     var value;
     for(var key in obj){
     // 通過 hasOwnProperty 過濾掉一個對象本身擁有的屬性 
     if(obj.hasOwnProperty(key)){
     value = obj[key];
     // 遞歸調用 循環所有對象出來
     if(typeof value === 'object'){
     if (Array.isArray(value)) {
     var augment = value.__proto__ ? protoAugment : copyAugment 
     augment(value, arrayMethods, key)
     observeArray(value)
     }
     new Observer(value);
     }
     this.convert(key, value);
     }
     }
    };
    
    p.convert = function(key, value){
     Object.defineProperty(this.data, key, {
     enumerable: true,
     configurable: true,
     get: function(){
     console.log(key + '被訪問');
     return value;
     },
     set: function(newVal){
     console.log(key + '被修改,新' + key + '=' + newVal);
     if(newVal === value) return ;
     value = newVal;
     }
     })
    }; 
    
    var data = {
     user: {
     // name: 'zhangsan',
     age: function(){console.log(1)}
     },
     apg: [{'a': 'b'},2,3]
    }
    
    function observeArray (items) {
     for (var i = 0, l = items.length; i < l; i++) {
     observe(items[i])
     }
    }
    
    //數據重復Observer
    function observe(value){
     if(typeof(value) != 'object' ) return;
     var ob = new Observer(value)
     return ob;
    }
    
    //輔助方法
    function def (obj, key, val) {
     Object.defineProperty(obj, key, {
     value: val,
     enumerable: true,
     writable: true,
     configurable: true
     })
    }
    
    // 兼容不支持__proto__的方法
    //重新賦值Array的__proto__屬性
    function protoAugment (target,src) {
     target.__proto__ = src
    }
    //不支持__proto__的直接修改相關屬性方法
    function copyAugment (target, src, keys) {
     for (var i = 0, l = keys.length; i < l; i++) {
     var key = keys[i]
     def(target, key, src[key])
     }
    }
    
    var app = new Observer(data);
    // data.apg[2] = 111;
    data.apg.push(5);
    // data.apg[0].a = 10;
    // console.log(data.apg);

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    vue源碼學習之Object.defineProperty 對數組監聽

    vue源碼學習之Object.defineProperty 對數組監聽:上一篇中,我們介紹了一下defineProperty 對對象的監聽,這一篇我們看下defineProperty 對數組的監聽 數組的變化 先讓我們了解下Object.defineProperty()對數組變化的跟蹤情況: var a={}; bValue=1; Object.defineProper
    推薦度:
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产一区二区精品尤物| 四虎影视永久在线精品| 国产精品国产三级国产潘金莲| 国产精品美女WWW爽爽爽视频| 亚洲成人精品久久| 亚洲Av永久无码精品三区在线 | 精品无码久久久久国产| 国产精品久久久99| 精品一区二区三区免费| 日韩精品一区二区三区色欲AV| 99re6在线视频精品免费| 亚洲爆乳精品无码一区二区三区 | 国产午夜精品理论片久久| 成人国产精品999视频| 亚洲国产精品无码久久98| 久久精品99无色码中文字幕| 国产精品免费视频观看拍拍| 久久青青草原国产精品免费| 国产午夜无码精品免费看动漫| 中文字幕精品一区二区日本| 国产精品无码无片在线观看| 久久精品人人做人人妻人人玩| 国产999精品久久久久久| 亚洲欧洲国产日韩精品| 久久精品国产久精国产| 国产精品欧美一区二区三区不卡 | 国产精品日韩AV在线播放| 合区精品中文字幕| 日韩午夜高清福利片在线观看欧美亚洲精品suv | 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 老司机99精品99| 国产精品禁18久久久夂久| 国产精品无套内射迪丽热巴| 国产精品美女久久久m| 国产精品内射后入合集| 1000部精品久久久久久久久 | 国产精品白浆在线观看免费| 久久发布国产伦子伦精品| 久久亚洲精品国产精品| 国产美女精品一区二区三区 | 欧美精品一区二区三区免费观看 |