<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何在不看源碼情況下學(xué) petite-vue 源碼

          共 2759字,需瀏覽 6分鐘

           ·

          2021-11-05 14:52

          作者:卡頌
          來源:SegmentFault 思否社區(qū)

          大家好,我是卡頌。

          周末沒啥事,準(zhǔn)備找個優(yōu)秀且代碼量不多的庫學(xué)習(xí)下。最終選擇了最近發(fā)布的petite-vue,原因如下:

          • 代碼量少(只有5.8kb),且源碼模塊化程度高(相比于React),易讀

          • 基于Vite構(gòu)建,執(zhí)行yarn dev就能開始調(diào)試源碼

          • 沒有虛擬DOM、編譯時(shí)方案,可以作為讀Vue源碼的鋪墊

          • 底層的響應(yīng)式更新原理同樣適用于Mobx、SolidJS等庫,一次閱讀多份收獲


          就決定是他了。


          但是周末時(shí)間這么寶貴,而且我都4年沒用過Vue了,如何才能高效學(xué)習(xí)源碼呢?
          最好是在不看源碼的情況下把源碼學(xué)了。
          接下來,我以petite-vue為例為大家示范學(xué)源碼的正確姿勢。

          怎么快怎么來

          可以將petite-vue理解為:用真實(shí)DOM取代Vue模版的簡易Vue。
          比如如下Demo
          <script type="module">
            import { createApp } from '../src'
            createApp({count: 0}).mount()
          </script>

          <div v-scope>
            <button @click="count++">add 1</button>
            <p>{{count}}</p>
          </div>  
          div及其子孫節(jié)點(diǎn)是真實(shí)的DOM標(biāo)簽,所以頁面初始化時(shí)如下:


          接著執(zhí)行如下代碼,完成petite-vue初始化:
          createApp({count: 0}).mount()
          此時(shí)頁面:


          讀框架源碼切忌一上手就從入口函數(shù)一路調(diào)試,很容易就懵逼了。正確的方式是像剝洋蔥一樣一層一層剝開:


          所以,讓我們先從Performance面板看看首屏渲染的調(diào)用棧:


          調(diào)用棧大體分為藍(lán)框、紅框兩部分,先看左邊藍(lán)框部分:


          通過createContextreactive關(guān)鍵詞判斷大概是創(chuàng)建響應(yīng)式上下文。至于響應(yīng)式的含義,我們還不清楚。
          接著看右邊紅框部分:


          從調(diào)用棧深度、頁面渲染的效果我們猜測,這部分做的工作包括:
          • 遍歷DOM

          • 完成數(shù)據(jù)與視圖的雙向綁定

          • 初始化渲染


          接下來,我們來驗(yàn)證猜想。
          注意,到目前為止,我們一行源碼都還沒看

          驗(yàn)證遍歷DOM

          調(diào)用棧中walkwalkChildren被調(diào)用多次,大概率他們就是具體遍歷工作執(zhí)行的方法,讓我們確認(rèn)下。
          在源碼walk方法中打上log
          export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
            console.log('walk', node);
            // ...  
          }
          排除換行符"\n "對應(yīng)的文本節(jié)點(diǎn),打印順序如下:
          walk div
          walk <button>add 1</button>
          walk "add 1"
          walk <p>0</p>
          walk "0"
          從打印結(jié)果看,這是個深度優(yōu)先遍歷(如果有子節(jié)點(diǎn)就遍歷子節(jié)點(diǎn),沒有子節(jié)點(diǎn)就遍歷兄弟節(jié)點(diǎn))
          顯然,petite-vue mount時(shí)采用深度優(yōu)先遍歷,并對遍歷到的每個與上下文狀態(tài)相關(guān)的DOM節(jié)點(diǎn)進(jìn)行處理。
          Demo中,上下文包含狀態(tài){count: 0}
          createApp({count: 0}).mount()
          在遍歷后<p>{{count}}</p>變?yōu)?/span><p>0</p>。

          確定雙向綁定的粒度

          接下來我們需要確認(rèn)雙向綁定的作用范圍,即:
          觸發(fā)更新后,多大范圍的DOM會被重新遍歷并執(zhí)行相應(yīng)DOM操作?
          打開Performance后,點(diǎn)擊<button>add 1</button>觸發(fā)更新:


          可以看到,沒有任何walk、walkChildren(或類似遍歷過程),只調(diào)用了reactiveEffect一個方法就更新了DOM。
          這意味著mount時(shí)的深度優(yōu)先遍歷建立了狀態(tài)更新DOM的方法之間一一對應(yīng)的關(guān)系。
          因?yàn)閷?yīng)關(guān)系確定了,就不再需要額外的遍歷過程確定需要變化的DOM。
          當(dāng)更新狀態(tài)后,只需要找到與他有關(guān)系的更新DOM的方法執(zhí)行就行。
          比如:將count狀態(tài)與如下函數(shù)建立聯(lián)系:
          function setCount(value) {
            p.textContent = value;
          }
          每當(dāng)count變化后調(diào)用setCount(count)就能更新p對應(yīng)DOM
          所以,petite-vue的工作原理,主要包括兩點(diǎn):
          1. mount時(shí)深度優(yōu)先遍歷DOM,對有狀態(tài)的DOM(比如<p>{{count}}</p>)建立狀態(tài)更新DOM的方法之間一一對應(yīng)的關(guān)系

          2. update時(shí)找到該狀態(tài)對應(yīng)的更新DOM的方法并執(zhí)行


          可以看到,即使不深入源碼,也能大體了解工作流程。
          如果你想更進(jìn)一步,比如了解關(guān)系是如何建立的(涉及到響應(yīng)式更新),那么就需要深入源碼了。
          這里推薦Vue MasteryVue 3 Reactivity課程,可以補(bǔ)齊響應(yīng)式更新這塊知識。


          總結(jié)

          本文介紹了復(fù)雜框架源碼的閱讀辦法 —— 即從抽象到具體。
          1. mount時(shí)與update時(shí)的調(diào)用棧推導(dǎo)出整體工作流程

          2. 整體工作流程中發(fā)現(xiàn)核心知識 —— 響應(yīng)式更新


          當(dāng)掌握整體工作流程響應(yīng)式更新后,再閱讀自己感興趣的部分才不至于陷入龐大的代碼量中。
          你,學(xué)廢了么?


          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 58
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大屌操肥逼| 亚洲AV综合色区无码国产网站 | 中文不卡视频 | 欧美视频中文字幕 | 中文字幕一区二区无码成人 |