Vue3全局組件注冊的實現(xiàn)代碼
1. 全局組件注冊
組件注冊在Vue
的官方文檔中有詳細的介紹,我們可以通過app.component
方法來注冊一個全局組件,如下所示:
import { createApp } from 'vue' const app = createApp({}) app.component('component-a', { /* ... */ })
注冊組件在Vue
中是非常簡單的一個操作,但是在Vue3
中,我們需要知道的是,Vue3
是如何將我們注冊的組件掛載到app
實例上的呢?
參考鏈接
2. 全局組件注冊實現(xiàn)
我們可以在組件注冊的代碼上面打上斷點,在瀏覽器中執(zhí)行一下,然后我們就可以看到Vue3
是如何將我們注冊的組件掛載到app
實例上的了。
當(dāng)我們跟蹤進入component
方法中,可以看到源碼實現(xiàn)很少,如下所示:
function component(name, component) { { // 1. 校驗組件名稱是否合法 validateComponentName(name, context.config); } // 2. 如果沒有傳遞組件,則返回已經(jīng)注冊的組件 if (!component) { return context.components[name]; } // 3. 如果傳遞了組件,并且組件已經(jīng)注冊,則打印警告信息提示組件已經(jīng)注冊 if (context.components[name]) { warn(`Component "${name}" has already been registered in target app.`); } // 4. 將組件直接賦值給 app 實例的 components 屬性中 context.components[name] = component; // 5. 返回 app 實例 return app; }
組件注冊整體來說是非常簡單的一個操作,我們可以看到,Vue3
在注冊組件的時候,主要做了以下幾件事情:
- 校驗組件名稱是否合法
- 如果沒有傳遞組件,則返回已經(jīng)注冊的組件,這一步對應(yīng)著已注冊組件的獲取
- 如果傳遞了組件,并且組件已經(jīng)注冊,則打印警告信息提示組件已經(jīng)注冊,這里少提示了一個警告信息,就是會將已注冊的組件覆蓋
- 將組件直接賦值給 app 實例的 components 屬性中,這里只是緩存下來,并不會使用
- 返回 app 實例,這里返回 app 實例主要是用于鏈?zhǔn)秸{(diào)用
3. 組件名稱規(guī)則
在Vue
的風(fēng)格指南中有明確的組件名稱規(guī)則,而在組件注冊的第一步也是校驗組件名稱是否合法,那么我們就來看一下Vue
的組件名稱規(guī)則。
我們可以繼續(xù)跟隨源碼來查看validateComponentName
方法的實現(xiàn),如下所示:
function validateComponentName(name, config) { // 1. 獲取內(nèi)部配置的 isNativeTag 方法來判斷是否是 HTML 原生標(biāo)簽 const appIsNativeTag = config.isNativeTag || NO; // 2. 判斷組件名是否是內(nèi)置的標(biāo)簽名或者是原生標(biāo)簽名 if (isBuiltInTag(name) || appIsNativeTag(name)) { // 3. 如果是內(nèi)置的標(biāo)簽名或者是原生標(biāo)簽名,則打印警告信息 warn( "Do not use built-in or reserved HTML elements as component id: " + name ); } }
我們可以看到,Vue
的組件名稱規(guī)則主要是校驗組件名稱是否是內(nèi)置的標(biāo)簽名或者是原生標(biāo)簽名,如果是,則會打印警告信息。
isNativeTag
的配置在官網(wǎng)中并沒有明確的說明,我們可以繼續(xù)跟蹤源碼來查看isNativeTag
的實現(xiàn),如下所示:
function injectNativeTagCheck(app) { Object.defineProperty(app.config, "isNativeTag", { value: (tag) => isHTMLTag(tag) || isSVGTag(tag), writable: false }); }
它是通過Object.defineProperty
方法來定義的,并且writable
為false
表示不可修改,我們可以看到,isNativeTag
的實現(xiàn)是通過isHTMLTag
和isSVGTag
來判斷的;
這里就沒有必要在繼續(xù)看了,反正我們熟知的div/span/button
等等html
標(biāo)簽肯定是不行的,然后就是svg/path/group
等等svg
標(biāo)簽也是不行的,這里就不一一列舉了。
再就是isBuiltInTag
他是通過makeMap
方法來實現(xiàn)的。
const isBuiltInTag = /* @__PURE__ */ makeMap("slot,component");
這里只有兩個組件,一個是slot
,一個是component
,不知道為什么不包含transition
,這里就不深究了。
風(fēng)格指南參考鏈接:
Vue3 的風(fēng)格指南對比 Vue2 的風(fēng)格指南少了很多,但是核心理念還是一致的,所以我們可以參考 Vue2 的風(fēng)格指南來學(xué)習(xí) Vue3 的風(fēng)格指南。
4. 組件掛載
在我們之前的章節(jié)中也講過組件的掛載,但是那個講的是一個組件是如何掛載到頁面上的,并沒有涉及到組件是如何從實例中獲取的,這次我們就來看一下組件是如何從實例中獲取的。
根據(jù)我們之前學(xué)習(xí)的章節(jié),我們知道一個組件最后會通過createVNode
方法來創(chuàng)建一個虛擬節(jié)點,然后通過render
方法來渲染到頁面上;
而虛擬節(jié)點上會有一個type
屬性和一個shapeFlag
屬性,type
屬性就是我們的組件,shapeFlag
屬性就是一個標(biāo)識,用于標(biāo)識當(dāng)前節(jié)點的類型。
而我們的組件最后在Vue
的內(nèi)部都是以對象的型式存在,所以shapeFlag
的值通常是4
,表示是一個對象,所以最后會執(zhí)行到mountComponent
方法中;
這里的組件是直接通過生成子樹,然后將子樹進行patch
的方式來掛載的,本質(zhì)上是和普通的元素掛載是一樣的;
由于這一塊我們是用模板語法來進行組件的使用的,這里的邏輯會比較復(fù)雜,在上面的組件掛載的文章中不能完全體現(xiàn), 模板本質(zhì)是一個字符串,最后會轉(zhuǎn)換成一個
ast
之后進行組件的匹配和掛載,內(nèi)容量會比較大,所以會在下一章進行詳細分析;
5. 總結(jié)
在這篇文章中,我們學(xué)習(xí)了Vue3
的全局組件注冊是如何實現(xiàn)的,主要是通過app.component
方法來實現(xiàn)的,component
方法內(nèi)部實現(xiàn)很簡單,主要有兩個功能:
- 注冊組件,但是組件只是以對象的方式緩存在
app
實例的components
屬性中,并沒有使用; - 獲取已經(jīng)注冊的組件,如果沒有傳遞組件,則通過組件名稱獲取已經(jīng)注冊的組件,這一步就是一個函數(shù)重載;
而組件掛載的過程和普通元素的掛載是一樣的,都是通過patch
的方式來進行的,這里就不再贅述了。
以上就是Vue3全局組件注冊的實現(xiàn)代碼的詳細內(nèi)容,更多關(guān)于Vue3全局組件注冊的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue 使用localstorage實現(xiàn)面包屑的操作
這篇文章主要介紹了vue 使用localstorage實現(xiàn)面包屑的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11vue props傳值失敗 輸出undefined的解決方法
今天小編就為大家分享一篇vue props傳值失敗 輸出undefined的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09antd design table更改某行數(shù)據(jù)的樣式操作
這篇文章主要介紹了antd design table更改某行數(shù)據(jù)的樣式操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10