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