Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

記一次Vue render的踩坑

前言#

在前幾天做自己的玩具的時候,想要實現類似 Element plus 的 Message 組件,一樣是通過方法調起組件,於是就用到了 render💻,但是在銷毀組件的時候遇到了一點小問題……

思路#

  • Message 組件,使用 transition 標籤控制其掛載以及銷毀動畫
  • message.ts,使用 createVNode 創建 VNode,使用 render 方法掛載到指定 div
  • setTimeout 倒計時設置銷毀該 Message 組件

這個時候問題就來了,在第一次渲染的時候,Message 組件確實展示出來了,在 3s 後也確實刪除掉了對應的 dom,但是後續都渲染不出來這個 message 組件🥲

过程#

從 render 開始打斷點,可以看到 Vue 提供的 render 方法,container 是我們傳入的要掛載的 div,vnode 是我們使用 createVNode 創建的虛擬 dom,也可以看到這個時候代碼走了 patch 方法。

稍為看了下 patch 代碼,根據對 VNode 的 type 判斷以及斷點,可以看到我們的代碼走到了 processComponent 這個方法裡,並且傳了相關的參數

在這個方法裡邊,n1 是我們要掛載的 div 裡邊的 VNode,這也是我第一次掛載跟後續掛載組件的不同之處,在第一次掛載組件的時候,n1 是為 null 的,在後面我雖然刪除了組件,但是那也是直接刪除的真實 dom,並沒有刪掉裡邊的 VNode,這樣就導致直接走了 updateComponent 方法,即更新組件。在 updateComponent 方法裡邊,會根據新舊虛擬節點 VNode 上的屬性、指令、子節點等判斷是否需要更新組件,但無論怎樣,離我想要的掛載新 message 組件都相去甚遠😶‍🌫️

最後#

根據render方法裡也可以看到,如果需要卸載掉虛擬 dom,我們只需要把 vnode 參數傳 null 即可,然後讓虛擬 dom 去更新真實 dom,以此來卸載掉我們的 message 組件,而不是直接刪除真實 dom。

雖然這個問題不是什麼大問題,直接參考 Element plus 的 Message 組件也可以發現問題在哪裡並直接做修改,但是自己還是挺喜歡瞎折騰這個過程並且在這之後自己可以有一個比較明確的結果和認識😌

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。