Vue資料驅動類比實現3,vue資料類比實現

來源:互聯網
上載者:User

Vue資料驅動類比實現3,vue資料類比實現

一、前言

在"類比Vue之資料驅動2"中,我們實現了個Observer建構函式,通過它可以達到監聽已有資料data中的所有屬性。

但,倘若我們想在某個對象中,新增某個屬性呢?

如下:

那麼豈不是,新增的infor屬性,以及它的對象屬性,沒有得到監聽。

此時,應該怎麼處理呢?

通過走讀Vue源碼,發現他是採用另增屬性方法$set實現的。

就是說,如果我們採用常規方法為對象增加屬性(如上),我們沒法得知並監控它,所以,我們為每個對象擴充一個$set方法,用於另增屬性使用,即可,如下:

data.user.$set('infor', {msg: 'happy'});

好了,下面,我們就一同實現這個$set方法吧。

二、$set方法實現

首先,我們得建立一個恒定extendObj對象,用於將$set方法綁定在其中。

你可能會想,為什麼我們需要一個extendObj對象呢?直接將$set函數賦值給每個需要監聽的對象不就完了嗎?

是的,這樣也可以,但是隨著需求增長,倘若我們又想為每個監聽對象擴充其他方法呢?難道又要去Observer裡面為對象,一一賦值?

so,建立恒定extendObj對象,如下:

const extendObj = {};

因為,我們將$set綁定到extendObj中,且讓$set為不可枚舉型,所以會用到Object.defineProperty,固將其提取出來,作為一個方法如下:

function proxyObject(obj, key, val, enume){  Object.defineProperty(obj, key, {    value: val,    enumerable: !!enume,    writable: true,    configurable: true  });  };

接下來,就是實現$set方法了,整體結構如下:

proxyObject(extendObj, '$set', function(key, val){  //this指向extendObj  if(this.hasOwnProperty(key)){    return;  }else{    /*     TODO:在extendObj中監聽key屬性,     且,若key屬性值為對象,再次監聽key屬性值    */       }  });

看到上面的TODO注釋,是否似曾相識,不就是是在“類比Vue之資料驅動2”遇見過的嘛,通過Observer.prototype.convert監聽key屬性,通過new Observer再次監聽key屬性值不就完啦。

的確,但是一旦這樣做了,不就和上面我們提到的“直接將$set賦予監聽對象”問題一樣嘛,耦合性太大,且隨著需求上漲,不易維護。

固而,在此需要一點小技巧:在observer模組中為每個監聽對象賦予一個$Observer屬性,其值指向Observer自身執行個體,如下:

//observer.jsp.walk = function(data){  let keys = Object.keys(data);  keys.forEach( key => {    let val = data[key];    if(typeof val === 'object'){      new Observer(val);    }    this.convert(key, val);  });  //$Observer屬性指向Observer自身執行個體  data.$Observer = this;}//新增一個observe方法p.observe = function(data){  if(typeof data === 'object'){    new Observer(data);    }  }

好了,這樣之後,得$set整體實現如下:

proxyObject(extendObj, '$set', function(key, val){  if(this.hasOwnProperty(key)){    return;  }else{    proxyObject(this, key, val, true);    let ob = this.$Observer;    ob.observe(val);    ob.convert(key, val);    }  });

到此,一個簡單的$set方法構建完畢。

在上面我們提到,之所以需要一個恒定extendObj對象,是為了更好的代碼管理。且,到目前為止,需要監聽的對象上並沒有擴充$set方法呢,所以,下面的事情就是為了達到以上效果,如下:

//observer.jsfunction Observer(data){  if(!(this instanceof Observer)){    return new Observer(data);  }  //將監聽對象的隱指標指向我們的extendObj對象  data.__proto__ = extendObj;  this.data = data;  this.walk(data);  }

好了,一切完畢,接下來就測試下吧:

<script src="./extendObj.js"></script><script src="./observer.js"></script><script>  let data = {    user: {      name: 'Monkey',      age: 24    },    lover: {      name: 'Dorie',      age: 23    }  };  Observer(data);</script>

效果如下:

Perfect,完整代碼見github。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.