<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答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
        主站蜘蛛池模板: 亚洲熟女一区二区三区| 亚洲国产精品一区二区三区久久 | 亚洲国产精品VA在线看黑人| 国产成人免费a在线视频app | 亚洲精品一品区二品区三品区| 国产午夜鲁丝片AV无码免费| 99亚偷拍自图区亚洲| 曰批全过程免费视频在线观看| 久久国内免费视频| 亚洲小说图片视频| 啦啦啦中文在线观看电视剧免费版| 亚洲精品无码99在线观看| 日韩精品无码永久免费网站| 亚洲情侣偷拍精品| 亚洲熟女乱色一区二区三区| 免费无码又爽又刺激一高潮| 亚洲国产成人一区二区三区| 国产精品免费AV片在线观看| 亚洲妇女水蜜桃av网网站| 成人免费午夜在线观看| 相泽南亚洲一区二区在线播放| 噼里啪啦免费观看高清动漫4 | 久久久久亚洲精品无码网址| 亚洲色成人WWW永久在线观看| 97se亚洲综合在线| 亚洲伊人精品综合在合线| 亚洲偷自拍另类图片二区| 日本高清免费中文字幕不卡| 国产成人精品日本亚洲专区| 成人性生交大片免费看中文| 久久久久亚洲爆乳少妇无| 日韩人妻一区二区三区免费| 亚洲色最新高清av网站| 久久久久久精品免费免费自慰| 亚洲精品视频在线| 最近更新免费中文字幕大全| 亚洲人妻av伦理| 思思久久99热免费精品6| 久久99精品视免费看| 亚洲国产精品无码久久久不卡 | 亚洲午夜av影院|