国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue源碼解析(二)-MVVM雙向綁定&&Watcher介紹

miya / 624人閱讀

摘要:前言上一遍文章介紹了模版渲染的實現,這篇文章將繼續介紹雙向綁定的實現官網如下,當。

前言

上一遍文章介紹了Vue模版渲染的實現(https://segmentfault.com/a/11...),這篇文章將繼續介紹雙向綁定的實現

demo

官網demo如下,當data。message的值變化,input的value值也會相應的變化;當用戶改變input框中的內容時data.message的值也會跟著改變

new Vue({ el: "#app", template: `

Message is: {{ message }}

`, data(){ return { message: "jixiangwu", } } })
ViewModel變化 -> View更新

當數據變化時,視圖會直接更新,在本例中當data.message改變時,dom中綁定了data.message的視圖都會更新
上一篇文章中介紹過,new Vue的過程中會將template字符串轉換成render函數,render函數執行后會得到vnode對象(虛擬dom),在調用_update方法會將虛擬dom更新為真實的瀏覽器dom,代碼如下:

    updateComponent = function () {
    //vm._render()生成vnode對象,vm._update()更新dom
      vm._update(vm._render(), hydrating);
    };
    //對vue實例新建一個Watcher監聽對象,每當vm.data數據有變化,Watcher監聽到后負責調用updateComponent進行dom更新
    vm._watcher = new Watcher(vm, updateComponent, noop);

updateComponent方法在Watcher初始化時會調用一次,后續的調用就涉及到MVVM的機制了,讓我們從頭開始分析
Vue初始化時會對data中的所有屬性進行observe,調用defineReactive方法,將data屬性轉化為getter/setters存取方式。本文demo中的data={message:“jixiangwu”}相當于如下的調用:defineReactive(vm.data,"message",vm.data["message"])

//vue對象的生命周期中會調用initData方法
function initData (vm) {
   var data = vm.$options.data;
   observe(data, true /* asRootData */);
}
function observe (value, asRootData) {
    ob = new Observer(value);
}
//對data進行監聽
var Observer = function Observer (value) {
  if (Array.isArray(value)) {
    this.observeArray(value);
  } else {
    this.walk(value);
  }
}
//對data中的所有屬性調用defineReactive,將其轉化為getter/setters存取方式
//Walk through each property and convert them into getter/setters.
Observer.prototype.walk = function walk (obj) {
  var keys = Object.keys(obj);
  for (var i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i], obj[keys[i]]);
  }
};
function defineReactive(obj,key,val){
  //利用閉包為每個屬性綁定一個dep對象(可視為發布者,負責發布屬性是否有變化)
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      //每次new一個watcher(訂閱者)對象的時候需要計算依賴的dep對象,Dep.target就是當前正在計算依賴的watcher對象
      if (Dep.target) {
      //調用屬性的getter方法時,存在Dep.target則將當前dep和watcher綁定
        dep.depend();
      }
    },
    set: function reactiveSetter (newVal) {
      //調用屬性的setter方法時,dep同時發布一次屬性變化的通知到所有依賴的watcher對象
      dep.notify();
    }
  }
}

defineReactive用到了Object.defineProperty 方法,這也是vue不支持ie8的原因,這個方法的主要作用就是set和get函數,同時也可以看到vue針對data中的所有屬性都會new一個dep對象,dep對象里面會存放所有依賴此屬性的watcher對象,此處用到了發布/訂閱模式,dep和watcher分別是發布者和訂閱者,每當data中的屬性變化dep對象就會通知所有依賴的watcher去更新dom,下面詳細分析一下這個過程
上一篇提到,由于template中引用了{{ message }}屬性,因此render函數里面會調用到vm.meessage,這時就會觸發defineReactive設置的get方法,get方法里面就會進行(該屬性)依賴的收集,那么get方法里的Dep.target是啥呢?
上一篇提到dom初次渲染是通過(監聽整個模版的)watcher對象初始化時調用watcher.get方法實現的,watcher.get方法主要是計算getter函數的值(本例中是updateComponent,更新dom)和計算依賴(哪些屬性的dep對象),Dep.target就是當前接受計算(依賴)的全局惟一的watcher對象,具體方法如下:
1、pushTarget(this),將this(當前watcher對象)賦值給Dep.target
2、調用this.getter,this.getter會訪問所有依賴的屬性,同時觸發屬性的getter方法
3、調用屬性getter方法中的dep.depend(),完成dep和wathcher的綁定
4、popTarget()將Dep.target值設為targetStack棧中的上一個(沒有則為空)

// the current target watcher being evaluated.
// this is globally unique because there could be only one
// watcher being evaluated at any time.
// 英文注釋都是源碼作者的注釋
Dep.target = null;
var targetStack = [];
//Evaluate the getter, and re-collect dependencies.
Watcher.prototype.get = function get () {
  //將this賦值給Dep.target
  pushTarget(this);  
  //執行wacther的更新操作,本文中是執行updateComponent方法
  this.getter.call(vm);
  popTarget();
}
function pushTarget (_target) {
  if (Dep.target) { targetStack.push(Dep.target); }
  Dep.target = _target;
}
function popTarget () {
  Dep.target = targetStack.pop();
}

繼續看defineReactive中dep.depend方法干了啥,其實就是dep對象上維護了一個watcher對象的隊列,wathcer對象上也維護了一份dep的隊列

Dep.prototype.depend = function depend () {
  if (Dep.target) {
    Dep.target.addDep(this);
  }
};
Watcher.prototype.addDep = function addDep (dep) {
  var id = dep.id;
  //將dep對象加入到wather對象的newDeps隊列中
  this.newDepIds.add(id);
  this.newDeps.push(dep);
  if (!this.depIds.has(id)) {
    // 同時將watcher對象也加入到dep對象的subs隊列中
    dep.addSub(this);
  }
};
Dep.prototype.addSub = function addSub (sub) {
  this.subs.push(sub);
};

data值變化時會觸發setter方法中的dep.notify,通知綁定在dep對象上的所有watcher對象調用update方法更新視圖(watcher.update最終調用了updateComponent,用到了緩存隊列,不一定立即觸發)

Dep.prototype.notify = function notify () {
  // stabilize the subscriber list first
  var subs = this.subs.slice();
  for (var i = 0, l = subs.length; i < l; i++) {
    subs[i].update();
  }
};

總結
1、對data進行observe,針對data屬性調用Object.defineProperty設置getter和setter,同時綁定一個dep對象
2、new Watcher(vm, updateComponent, noop)監聽整個dom的變化
3、watcher初始化時調用updateComponent,updateComponent調用render函數更新dom(此時還會將該watcher對象賦值給全局對象Dep.target,進行依賴收集)
4、在watcher對象依賴收集期間,render函數訪問data中的屬性(如本例的data.message),觸發data.message的getter方法,在getter方法中會將data.message綁定的dep對象和wathcer對象建立對應關系(互相加入到對方維護的隊列屬性上)
5、后續data屬性的值變化時dep對象會通知所有依賴此data屬性的watcher對象調用updateComponent方法更新視圖

View變化 -> ViewModel更新

視圖變化 -> 數據更新主要是通過v-model實現的,v-model本質上不過是語法糖,它負責監聽用戶的輸入事件以更新數據,本例中

基本等同于下面的效果

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89511.html

相關文章

  • Vue源碼解析(三)-computed計算屬性&amp;&amp;lazy watcher

    摘要:前言源碼解析一模版渲染源碼解析二雙向綁定官網給出的如下結果源碼分析判斷參數是否包含屬性本例中本例中和是函數監聽計算屬性設置,延遲執行的方法設置可以通過本例方式訪問計算屬性對象初始化時會針對屬性的所有值分別一個對象,在源碼解析二中有詳細介 前言 1、Vue源碼解析(一)-模版渲染2、Vue源碼解析(二)-MVVM雙向綁定 demo 官網給出的demo如下 new Vue({ el...

    CoderStudy 評論0 收藏0
  • 剖析Vue原理&amp;實現雙向綁定MVVM

    摘要:所以無需太過介懷是實現的單向或雙向綁定。監聽數據綁定更新函數的處理是在這個方法中,通過添加回調來接收數據變化的通知至此,一個簡單的就完成了,完整代碼。 本文能幫你做什么?1、了解vue的雙向數據綁定原理以及核心代碼模塊2、緩解好奇心的同時了解如何實現雙向綁定為了便于說明原理與實現,本文相關代碼主要摘自vue源碼, 并進行了簡化改造,相對較簡陋,并未考慮到數組的處理、數據的循環依賴等,也...

    melody_lql 評論0 收藏0
  • VUE - MVVM - part13 - inject &amp; 總結

    摘要:通過裝作這些變化,我們實現了從而到達了數據變化觸發函數的過程。于此同時,我們還實現了來擴展這個可響應的結構,讓這個對象擁有了觸發和響應事件的能力。最后,根據我們的實現,這是最終的產出,一個框架,了解一下系列文章地址優化優化總結 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 provide / inject 在上一步我們實現了,父子組件,和 props 一樣 pr...

    niuxiaowei111 評論0 收藏0
  • VueJS源碼學習——項目結構&amp;目錄

    摘要:所以整個的核心,就是如何實現這三樣東西以上摘自囧克斯博客的一篇文章從版本開始這個時候的項目結構如下源碼在里面,為打包編譯的代碼,為打包后代碼放置的位置,為測試代碼目錄。節點類型摘自資源另一位作者關于源碼解析 本項目的源碼學習筆記是基于 Vue 1.0.9 版本的也就是最早的 tag 版本,之所以選擇這個版本,是因為這個是最原始沒有太多功能拓展的版本,有利于更好的看到 Vue 最開始的骨...

    ad6623 評論0 收藏0
  • 自己實現MVVMVue源碼解析

    摘要:無論是雙向綁定還是單向綁定,都是符合思想的。看了的源碼后不難發現的雙向綁定的實現也就是在表單元素上添加了事件,可以說雙向綁定是單向綁定的一個語法糖。 前言 本文會帶大家手動實現一個雙向綁定過程(僅僅涵蓋一些簡單的指令解析,如:v-text,v-model,插值),當然借鑒的是Vue1的源碼,相信大家在閱讀完本文后對Vue1會有一個更好的理解,源代碼放到了github,由于本人水平有限,...

    ?xiaoxiao, 評論0 收藏0

發表評論

0條評論

miya

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<