Vue響應(yīng)原理

Vue 的響應(yīng)依賴于Object.defineProperty,這也是Vue不支持IE8的原因。Vue通過設(shè)定對(duì)象屬性的setter/getter方法來(lái)監(jiān)聽數(shù)據(jù)的變化。通過getter進(jìn)行依賴收集,而每個(gè)setter方法就是一個(gè)觀察者,在數(shù)據(jù)變更的時(shí)候通知訂閱者更新視圖。


看看簡(jiǎn)單的雙向綁定實(shí)現(xiàn)

const obj = {

object.defineProperty(obj, 'hello', {
  get(value) {
    console.log('use get')
  },
  set(newVal, oldVal) {
    console.log('user')
  }


<input type="text" id="a"/>
<span id="b"></span>

<script>
    const obj = {};
    Object.defineProperty(obj,'hello',{
      get(){
        console.log("啦啦啦,方法被調(diào)用了");
      },
      set(newVal){
        document.getElementById('a').value = newVal;
        document.getElementById('b').innerHTML = newVal;
      }
    })
    document.addEventListener('keyup',function(e){
      obj.hello = e.target.value;
    })
</script>

將數(shù)據(jù)data變成可觀察(observable)

function observer(val) {
  Object
    .key
    .forEach((val) => {
       defineReactive(val, key, value[key], cb)
    })
}
function defineReactive(obj, key, val, cb) {
  Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get: () => {
        /*....依賴收集等....*/
            /*Github:https://github.com/answershuto*/
      },
      set: newVal => {
        cb();/*訂閱者收到消息的回調(diào)*/
      }
   })
}
class Vue {
   constructor(options) {
      this._data = options.data;
      observer(this._data, options.render)
    }
 }
let app = new Vue({
    el: '#app',
    data: {
        text: 'text',
        text2: 'text2'
    },
    render(){
        console.log("render");
    }
})

為了便于理解,首先考慮一種最簡(jiǎn)單的情況,不考慮數(shù)組等情況,代碼如上所示。在initData中會(huì)調(diào)用observe這個(gè)函數(shù)將Vue的數(shù)據(jù)設(shè)置成observable的。當(dāng)_data數(shù)據(jù)發(fā)生改變的時(shí)候就會(huì)觸發(fā)set,對(duì)訂閱者進(jìn)行回調(diào)(在這里是render)。

那么問題來(lái)了,需要對(duì)app._date.text操作才會(huì)觸發(fā)set。為了偷懶,我們需要一種方便的方法通過app.text直接設(shè)置就能觸發(fā)set對(duì)視圖進(jìn)行重繪。那么就需要用到代理。

代理

我們可以在Vue的構(gòu)造函數(shù)constructor中為data執(zhí)行一個(gè)代理proxy。這樣我們就把data上面的屬性代理到了vm實(shí)例上。

_proxy(options.data);/*構(gòu)造函數(shù)中*/

/*代理*/
function _proxy (data) {
   const that = this;
   Object.keys(data).forEach(key => {
       Object.defineProperty(that, key, {
           configurable: true,
           enumerable: true,
           get: function proxyGetter () {
               return that._data[key];
           },
           set: function proxySetter (val) {
               that._data[key] = val;
           }
       })
   });
}

我們就可以用app.text代替app._data.text了。

下面是一個(gè)模擬Vue數(shù)據(jù)綁定的方法


vue.png

(轉(zhuǎn))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對(duì)于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,177評(píng)論 0 29
  • 這方面的文章很多,但是我感覺很多寫的比較抽象,本文會(huì)通過舉例更詳細(xì)的解釋。(此文面向的Vue新手們,如果你是個(gè)大牛...
    Ivy_2016閱讀 15,576評(píng)論 8 63
  • 下載安裝搭建環(huán)境 可以選npm安裝,或者簡(jiǎn)單下載一個(gè)開發(fā)版的vue.js文件 瀏覽器打開加載有vue的文檔時(shí),控制...
    冥冥2017閱讀 6,197評(píng)論 0 42
  • 家,向來(lái)以溫馨的港灣著稱。一說(shuō)到家,往往就給人安全感和幸福感,而家里人的關(guān)切與問候更是漂泊在外的游子們的定心丸。父...
    一個(gè)皮球的自述閱讀 215評(píng)論 0 0

友情鏈接更多精彩內(nèi)容