vue的雙向數據綁定

雙向數據綁定,我們首先來看數據改變如何觸發頁面的刷新。
首先通過Object.defineProperty( )對vue的data設置getter和setter。實現攔截數據。我們的數據都是在html里以指令或者變量的形式存在。

一個笨辦法

遍歷全部DOM,把需要更新數據的DOM都和對應的數據映射起來,存在在一個對象中,就是一個數據一個對象。然后全部放在一個數組中。每當有數據變化,就去遍歷這個數組,把對應數據的DOM進行更新。這么做的缺點是每次都需要遍歷全部的數組。

別的辦法

一一對應的關系,是不是該用對象?想想node里路由傳參數的那個問題。我們一個對象例如為BInging:{},key是data的每個值,value是依賴這個數據的DOM。然后數據變化BInging[變化的數據]就可以取出value更新相關的DOM。

vue的方法

vue中并沒有專門設置這樣一個對象。而是把抵賴放入了data每個值得getter函數中。更新放進了setter中。就是吧獨立出來的BInging對象和data對象進行了融合。


因為這里的get和set會因為閉包造成作用域不被回收,所以dep會保存在每個data的get和set作用域中。

v-model更新數據

給v-model加上input監聽事件。觸發事件的時候去更新data的值。視圖自然就跟著變了。
實現雙向綁定MVVM
vue的雙向綁定原理及實現

vue雙向綁定數據原理
image

我們的目錄結構為

image.png
compile.js // 解析vue的DOM
dep.js // 增加監聽數據和Watcher中間的橋梁
index.js // 初始化操作
observer.js // 對data數據進行劫持
watcher // 數據變化需要通知的訂閱者

首先我們給vue的data的所以數據用Object.defineProperty
其次我們來解析DOM。
??采用遞歸方法從vue傳入的el(一般為el: '#app',)根元素進行向下遍歷。
目前我們先只考慮文本節點。只是把{{}}等解析成頁面展示的內容放入頁面內比較簡單。
??現在如果data的數據變化,頁面的內容也需要變化。這樣改怎樣做?
一個數據例如data下的name變化肯能頁面有多處用到這個變量。所以要把所有用到name變量的地方都進行更新。我們每個data有一個dep對象。用來存放所有的依賴。這就需要我們。變量DOM的時候,碰到name就把相應的dom更新函數存放到namedep中。在什么位置進行dep的存放呢?第一次變量DOM肯定會觸發變量的get。我們放到get函數中。

vue中,比較不好理解的就是Dep.target。為什么需要Dep.target

var uid = 0;

function Dep() {
    this.id = uid++;
    this.subs = [];
}
Dep.prototype = {
    addSub: function(sub) {
        this.subs.push(sub);
    },

    depend: function() {
        Dep.target.addDep(this);
    },

    removeSub: function(sub) {
        var index = this.subs.indexOf(sub);
        if (index != -1) {
            this.subs.splice(index, 1);
        }
    },

    notify: function() {
        this.subs.forEach(function(sub) {
            sub.update();
        });
    }
};

Dep.target = null; // 

只有獲取數據就會觸發get,但不能通過手動的alert(dat.name)這種代碼。也給dep增加依賴吧。這樣也沒有依賴可以加啊。所以Dep.target就是為了標志訂閱者Watcher的。就是只有我們new Watcher()的時候Dep.target值才為真,才會被添加到dep中。Dep.target 可以在watcher.jsobserver.js中通過 import Dep from './dep.js'來或者或者設置Dep.target這個變量。為什么不放在Dep構造函數的原型中呢?因為Dep.target 還需要通過watcher.js進行設置。這個Dep.target到底是什么有什么用處呢?

import Dep from './dep.js'
function Watcher () {
  this.get()
}
  get: function() {
        Dep.target = this;
        var value = this.getter.call(this.vm, this.vm); // 解析DOM中的表達式觸發data的get函數。
        Dep.target = null;
        return value;
    },

當觸發get函數時候設置Dep.target,經過判斷可以觸發dep.depend();或者dep.addSub(Dep.target)目的都是為了給dep中增加依賴的watcher。

  Dep.prototype  = {
   depend: function() {
        Dep.target.addDep(this); // Dep.target就是剛剛設置的Watcher實例
    },
  addSub:function() {
       this.subs.push(sub)
    },
  }

dep.depend();又轉而觸發了WatcheraddDep。為什么呢?
因為我們需要在dep中添加watcher實例。dep實例或者構造函數中并沒有watcher實例啊。所以只能把通過傳參數,把一方傳到另一方去進行二合一。這里把dep實例傳入到了watcher實例中。

addDep: function(dep) {
            dep.addSub(this); 
            this.depIds[dep.id] = dep;
    },

addDepthiswatcher實例depDep.target.addDep(this)this也就是dep實例。


然而發現直接dep.addSub(Dep.target)就可以實現把watcher添加到dep中。因為Dep.target就是watcher實例。
現在我們的datadep添加watcher完成,只需要在dataset函數觸發時候。遍歷dep中的subs進行觸發就可以達到更新頁面的效果

對應關系


簡易源碼分析1
簡易源碼分析2

vue中虛擬DOM的原理

虛擬DOM

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容