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

資訊專(zhuān)欄INFORMATION COLUMN

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

miya / 634人閱讀

摘要:前言上一遍文章介紹了模版渲染的實(shí)現(xiàn),這篇文章將繼續(xù)介紹雙向綁定的實(shí)現(xiàn)官網(wǎng)如下,當(dāng)。

前言

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

demo

官網(wǎng)demo如下,當(dāng)data。message的值變化,input的value值也會(huì)相應(yīng)的變化;當(dāng)用戶(hù)改變input框中的內(nèi)容時(shí)data.message的值也會(huì)跟著改變

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

Message is: {{ message }}

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

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

    updateComponent = function () {
    //vm._render()生成vnode對(duì)象,vm._update()更新dom
      vm._update(vm._render(), hydrating);
    };
    //對(duì)vue實(shí)例新建一個(gè)Watcher監(jiān)聽(tīng)對(duì)象,每當(dāng)vm.data數(shù)據(jù)有變化,Watcher監(jiān)聽(tīng)到后負(fù)責(zé)調(diào)用updateComponent進(jìn)行dom更新
    vm._watcher = new Watcher(vm, updateComponent, noop);

updateComponent方法在Watcher初始化時(shí)會(huì)調(diào)用一次,后續(xù)的調(diào)用就涉及到MVVM的機(jī)制了,讓我們從頭開(kāi)始分析
Vue初始化時(shí)會(huì)對(duì)data中的所有屬性進(jìn)行observe,調(diào)用defineReactive方法,將data屬性轉(zhuǎn)化為getter/setters存取方式。本文demo中的data={message:“jixiangwu”}相當(dāng)于如下的調(diào)用:defineReactive(vm.data,"message",vm.data["message"])

//vue對(duì)象的生命周期中會(huì)調(diào)用initData方法
function initData (vm) {
   var data = vm.$options.data;
   observe(data, true /* asRootData */);
}
function observe (value, asRootData) {
    ob = new Observer(value);
}
//對(duì)data進(jìn)行監(jiān)聽(tīng)
var Observer = function Observer (value) {
  if (Array.isArray(value)) {
    this.observeArray(value);
  } else {
    this.walk(value);
  }
}
//對(duì)data中的所有屬性調(diào)用defineReactive,將其轉(zhuǎn)化為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){
  //利用閉包為每個(gè)屬性綁定一個(gè)dep對(duì)象(可視為發(fā)布者,負(fù)責(zé)發(fā)布屬性是否有變化)
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      //每次new一個(gè)watcher(訂閱者)對(duì)象的時(shí)候需要計(jì)算依賴(lài)的dep對(duì)象,Dep.target就是當(dāng)前正在計(jì)算依賴(lài)的watcher對(duì)象
      if (Dep.target) {
      //調(diào)用屬性的getter方法時(shí),存在Dep.target則將當(dāng)前dep和watcher綁定
        dep.depend();
      }
    },
    set: function reactiveSetter (newVal) {
      //調(diào)用屬性的setter方法時(shí),dep同時(shí)發(fā)布一次屬性變化的通知到所有依賴(lài)的watcher對(duì)象
      dep.notify();
    }
  }
}

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

// 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);  
  //執(zhí)行wacther的更新操作,本文中是執(zhí)行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();
}

繼續(xù)看defineReactive中dep.depend方法干了啥,其實(shí)就是dep對(duì)象上維護(hù)了一個(gè)watcher對(duì)象的隊(duì)列,wathcer對(duì)象上也維護(hù)了一份dep的隊(duì)列

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

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

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();
  }
};

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

View變化 -> ViewModel更新

視圖變化 -> 數(shù)據(jù)更新主要是通過(guò)v-model實(shí)現(xiàn)的,v-model本質(zhì)上不過(guò)是語(yǔ)法糖,它負(fù)責(zé)監(jiān)聽(tīng)用戶(hù)的輸入事件以更新數(shù)據(jù),本例中

基本等同于下面的效果

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/89511.html

相關(guān)文章

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

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

    CoderStudy 評(píng)論0 收藏0
  • 剖析Vue原理&amp;實(shí)現(xiàn)雙向綁定MVVM

    摘要:所以無(wú)需太過(guò)介懷是實(shí)現(xiàn)的單向或雙向綁定。監(jiān)聽(tīng)數(shù)據(jù)綁定更新函數(shù)的處理是在這個(gè)方法中,通過(guò)添加回調(diào)來(lái)接收數(shù)據(jù)變化的通知至此,一個(gè)簡(jiǎn)單的就完成了,完整代碼。 本文能幫你做什么?1、了解vue的雙向數(shù)據(jù)綁定原理以及核心代碼模塊2、緩解好奇心的同時(shí)了解如何實(shí)現(xiàn)雙向綁定為了便于說(shuō)明原理與實(shí)現(xiàn),本文相關(guān)代碼主要摘自vue源碼, 并進(jìn)行了簡(jiǎn)化改造,相對(duì)較簡(jiǎn)陋,并未考慮到數(shù)組的處理、數(shù)據(jù)的循環(huán)依賴(lài)等,也...

    melody_lql 評(píng)論0 收藏0
  • VUE - MVVM - part13 - inject &amp; 總結(jié)

    摘要:通過(guò)裝作這些變化,我們實(shí)現(xiàn)了從而到達(dá)了數(shù)據(jù)變化觸發(fā)函數(shù)的過(guò)程。于此同時(shí),我們還實(shí)現(xiàn)了來(lái)擴(kuò)展這個(gè)可響應(yīng)的結(jié)構(gòu),讓這個(gè)對(duì)象擁有了觸發(fā)和響應(yīng)事件的能力。最后,根據(jù)我們的實(shí)現(xiàn),這是最終的產(chǎn)出,一個(gè)框架,了解一下系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒(méi)有看過(guò)之前的文章,移步拉到文章末尾查看之前的文章。 provide / inject 在上一步我們實(shí)現(xiàn)了,父子組件,和 props 一樣 pr...

    niuxiaowei111 評(píng)論0 收藏0
  • VueJS源碼學(xué)習(xí)——項(xiàng)目結(jié)構(gòu)&amp;目錄

    摘要:所以整個(gè)的核心,就是如何實(shí)現(xiàn)這三樣?xùn)|西以上摘自囧克斯博客的一篇文章從版本開(kāi)始這個(gè)時(shí)候的項(xiàng)目結(jié)構(gòu)如下源碼在里面,為打包編譯的代碼,為打包后代碼放置的位置,為測(cè)試代碼目錄。節(jié)點(diǎn)類(lèi)型摘自資源另一位作者關(guān)于源碼解析 本項(xiàng)目的源碼學(xué)習(xí)筆記是基于 Vue 1.0.9 版本的也就是最早的 tag 版本,之所以選擇這個(gè)版本,是因?yàn)檫@個(gè)是最原始沒(méi)有太多功能拓展的版本,有利于更好的看到 Vue 最開(kāi)始的骨...

    ad6623 評(píng)論0 收藏0
  • 自己實(shí)現(xiàn)MVVMVue源碼解析

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

    ?xiaoxiao, 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

miya

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<