對Vue原理的一些認(rèn)識和簡單實現(xiàn)

用vue也有很長一段時間锹淌,用它做過移動端項目 pc項目 SaaS平臺等等贷掖,總體來說vue 還是相對于簡單的识啦、建立于良好的文檔和開箱即用的腳手架, vue在前端框架的熱度一直很高, 最近正好在研究vue的源碼 畢竟學(xué)習(xí)之路基本都是學(xué)輪子 -> 看源碼 -> 造輪子 ????逐步精進來的, 網(wǎng)上有非常多的vue的原理解析的文章箕憾,可能我寫的不算太好 不過還是寫下來作為一個積累和總結(jié)

大概思路

vue的數(shù)據(jù)驅(qū)動主要實現(xiàn)建立在三個對象上Dep卿啡、Watcher昔瞧、Compiler,

Dep 主要負(fù)責(zé)依賴的收集
Watcher 主要負(fù)責(zé)Dep和Compiler之間的聯(lián)系
Compiler 可以理解為 virtual dom + patch 也就是負(fù)責(zé)視圖層的渲染

可以用個簡單的思維導(dǎo)圖來說明下大概原理


image.png

1. getter指蚁、setter

首先我們可以看到通過Object.defineProperty為vm實例定義了一個getter、setter. 我們可以將兩個分開來講:

getter

getter: 主要是獲取到對應(yīng)的鍵值, 這里有一個步驟是先將原來的getter和setter提取出來自晰,這一步主要是為了防止預(yù)定義的getter和setter凝化,保證預(yù)定義getter、setter一樣能夠生效, 注意到有一步是判斷Dep.target, 有的話就收集依賴了酬荞。還有一些對于數(shù)組的處理, 這里就不細(xì)述了搓劫。

setter

setter: 在setter函數(shù)中,主要是對相同的值的攔截混巧,然后對于嵌套對象的重新observe枪向,這里之所以會重新observe 是因為vue在每次響應(yīng)了數(shù)據(jù)變化后,會清除掉所有的依賴咧党,因此要重新建立, 至于為什么會重新建立 我們會在下面大概說下, 當(dāng)值發(fā)生變化時秘蛔,最后會觸發(fā)dep.notify(), 來觸發(fā)依賴的升級.

2. 依賴的建立

在代碼中我們可以看到依賴的建立是通過dep.depend()來完成的, 那這個過程是在什么時候完成的呢

mountComponet.png

其實我們可以看到在 mountComponent中會new 一個 watcher實例,還有就是有一個叫做updateComponent的函數(shù)產(chǎn)生,這一個函數(shù)的主要作用就是視圖層渲染更新, new Watcher參數(shù)中的before會觸發(fā)生命周期beforeUpdate的鉤子傍衡, 好了 接下來我們來看下new Watcher的時候都發(fā)生了些什么?
watcher 構(gòu)造器函數(shù)

我們能看到watcher在實例化的過程中會有大量屬性深员,然后會根據(jù)是否是計算屬性來進行判斷, 我們這里先不去管計算屬性, 直接就從最簡單的data進行入手, 會觸發(fā)watcher.get()

watcher.get

這里的getter 其實就是updateComponent 函數(shù), 在updateComponent函數(shù)中會通過virtual dom 和 patch函數(shù)來進行視圖層的更新和渲染。在分析template建立虛擬dom的過程中需要去獲取vm的屬性蛙埂, 因此會觸發(fā)vm.getter函數(shù)

pushTarget() // 將當(dāng)前的watcher 實例 設(shè)置為 Dep.target

然后會觸發(fā)dep.depend()


dep.depend

這時候我們能看到Dep.target 其實就是當(dāng)前的watcher實例.


watcher.addDep

這邊有一個判斷是防止重復(fù)依賴產(chǎn)生倦畅,最后就是dep.addSub()


dep.addSub

最后通過subs來存儲watcher

3.屬性變化后 依賴通知watcher進行update

還記得上面提到的setter嗎?(不清楚的話绣的,可以拉上去看下) setter會在屬性值發(fā)生變化時叠赐,觸發(fā)dep.notify()

dep.notify

subs里面的都是收集到的watcher實例
watcher.update

這里我們看到會有一個queueWatcher的函數(shù), 這個其實是將當(dāng)前watcher 弄到一個tick中去,這塊涉及到j(luò)s eventLoop
機制這一塊. 我們放到后續(xù)的文章去講,到最后的話, 其實是會觸發(fā)到watcher.run()
watcher.run & watcher.getAndInvoke

我們看到這個里面會有觸發(fā)watcher.get(), 翻到上面的截圖, 我們會發(fā)現(xiàn)get 會觸發(fā)updateComponent 這時候就完成了整個視圖層的更新屡江。

一些問題

  • 為什么vue在每次都要清除一下已有的一些依賴
    其實這個問題我剛開始也很疑惑芭概,既然依賴已經(jīng)建立,那為什么還要清理掉又重新建立呢惩嘉,所以我打開了google谈山,找到了這樣一個解釋


    image.png

    目前的話,其實還不太理解宏怔, 下次我會找個機會做個demo 嘗試下

  • vue是如何基于event loop實現(xiàn)的nextTick?
    這一塊的話還是比較生疏奏路,源碼我會繼續(xù)往下面看畴椰,到時候會寫一篇關(guān)于js event loop的博文以及nextTick的實現(xiàn)來作為學(xué)習(xí)總結(jié).

結(jié)語

其實我覺得vue的原理基本上就相當(dāng)于代理者模式+訂閱發(fā)布模式來實現(xiàn)的, 說實話第一次看這種源碼還挺懵逼的,不過我覺得看源碼就要直奔主題鸽粉,先把主枝干理清除斜脂,了解自己想要得到什么,整個過程就會清晰明了, 主要放一個自己的ts版的簡單實現(xiàn)触机,寫的很簡陋帚戳,但是能夠大概看出vue的原理,有興趣的可以看下 ts版vue簡易原理

參考

  • vue core
  • Vue.js 技術(shù)揭秘 // 這個是我在看源碼后有一些不理解的問題google時候搜到的儡首,寫的非常好片任,不想直接看源碼的可以直接看這個
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蔬胯,隨后出現(xiàn)的幾起案子对供,更是在濱河造成了極大的恐慌,老刑警劉巖氛濒,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件产场,死亡現(xiàn)場離奇詭異,居然都是意外死亡舞竿,警方通過查閱死者的電腦和手機京景,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骗奖,“玉大人确徙,你說我怎么就攤上這事≈醋溃” “怎么了鄙皇?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鼻吮。 經(jīng)常有香客問我,道長较鼓,這世上最難降的妖魔是什么椎木? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮博烂,結(jié)果婚禮上香椎,老公的妹妹穿的比我還像新娘。我一直安慰自己禽篱,他們只是感情好畜伐,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著躺率,像睡著了一般玛界。 火紅的嫁衣襯著肌膚如雪万矾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天慎框,我揣著相機與錄音良狈,去河邊找鬼。 笑死笨枯,一個胖子當(dāng)著我的面吹牛薪丁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播馅精,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼严嗜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了洲敢?” 一聲冷哼從身側(cè)響起漫玄,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沦疾,沒想到半個月后称近,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡哮塞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年刨秆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忆畅。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡衡未,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出家凯,到底是詐尸還是另有隱情缓醋,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布绊诲,位于F島的核電站送粱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掂之。R本人自食惡果不足惜抗俄,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望世舰。 院中可真熱鬧动雹,春花似錦、人聲如沸跟压。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至茸塞,卻和暖如春躲庄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翔横。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工读跷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人禾唁。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓效览,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荡短。 傳聞我的和親對象是個殘疾皇子丐枉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容