Vue動(dòng)態(tài)組件和異步組件原理詳解
前言
在vue官方資料中,我們可以可以很學(xué)會(huì)如何通過(guò)vue構(gòu)建“動(dòng)態(tài)組件”以及“異步組件”,然而,在官方資料中,并沒(méi)有涉及到真正的“動(dòng)態(tài)異步”組件,經(jīng)過(guò)大量的時(shí)間研究和技術(shù)分析,我們給出目前比較合理的技術(shù)實(shí)現(xiàn)方式,并分析一下vue動(dòng)態(tài)異步組件的原理
動(dòng)態(tài)組件 & 異步組件的存在,使得我們更方便地控制首屏代碼的體積,加快加載速度。
拋開(kāi)具體細(xì)節(jié)不談,一個(gè)普通 Vue 組件從創(chuàng)建到展現(xiàn)在頁(yè)面里,主要經(jīng)歷了以下流程:
// 組件 Object
{
template: '<div>I am async!</div>'
}
// 經(jīng)過(guò) compileToFunctions 得到對(duì)應(yīng)的 render function
with(this) {
return _c('div', [_v("I am async!")])
}
// 在經(jīng)過(guò) render 得到 Vnode 再 update 成為真實(shí)DOM
動(dòng)態(tài)組件&異步組件與之有什么區(qū)別呢?
主要區(qū)別在于 render 中 createComponent 這一步,舉例。
// 組件
Vue.component('example', {
template: '<div>I am async!</div>'
})
普通組件在 createComponent 時(shí),會(huì)依據(jù)開(kāi)發(fā)者自定義的 options,利用 Vue.extend 生成對(duì)應(yīng)的構(gòu)造函數(shù),從而得到對(duì)應(yīng)的 Vnode 。而一個(gè)異步組件
// 異步組件
Vue.component('async-example', function (resolve, reject) {
// 利用 setTimeout 模擬請(qǐng)求
setTimeout(function () {
// 向 `resolve` 回調(diào)傳遞組件定義
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
則是要經(jīng)過(guò)一系列處理,具體過(guò)程如下
在源碼的 create-component。
// async component
let asyncFactory
if (isUndef(Ctor.cid)) {
asyncFactory = Ctor
Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
if (Ctor === undefined) {
// return a placeholder node for async component, which is rendered
// as a comment node but preserves all the raw information for the node.
// the information will be used for async server-rendering and hydration.
return createAsyncPlaceholder(
asyncFactory,
data,
context,
children,
tag
)
}
}
首先 Ctor 就與之前不同,這里為一個(gè) function
function (resolve, reject) {
// 利用 setTimeout 模擬請(qǐng)求
setTimeout(function () {
// 向 `resolve` 回調(diào)傳遞組件定義
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
}
之后調(diào)用 resolveAsyncComponent(asyncFactory, baseCtor, context)
resolveAsyncComponent 在源碼的 resolveAsyncComponent。
resolveAsyncComponent 的主要功能是定義 Ctor 所需要的 resolve 、reject 函數(shù)
// factory 為 Ctor factory(resolve, reject)
以 resolve 函數(shù)為例
const resolve = once((res: Object | Class<Component>) => {
// 緩存 resolved
factory.resolved = ensureCtor(res, baseCtor)
// 強(qiáng)制渲染
if (!sync) {
forceRender(true)
}
})
once 字面理解,就是只調(diào)用一次。當(dāng) Ctor 中 setTimeout 結(jié)束時(shí)調(diào)用。
ensureCtor 就是 Vue.extend 的封裝以適應(yīng)不同場(chǎng)景,所以 resolve 函數(shù)的主要功能就是在異步完成時(shí),將得到的 Ctor 轉(zhuǎn)化為構(gòu)造函數(shù),緩存在 factory.resolved 中。
之后利用 forceRender(true) 強(qiáng)制重新 render,由于之前緩存了 factory.resolved,resolveAsyncComponent 函數(shù)就直接返回了組件的構(gòu)造函數(shù)。
if (isDef(factory.resolved)) {
return factory.resolved
}
之后就與普通組件一致了。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
vue.js?Table?組件自定義列寬實(shí)現(xiàn)核心方法
這篇文章主要介紹了vue.js?Table?組件自定義列寬實(shí)現(xiàn)核心方法,文圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07
effect返回runner單測(cè)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了effect返回runner單測(cè)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
詳解vue中父子組件傳遞參數(shù)props的實(shí)現(xiàn)方式
這篇文章主要給大家介紹了在vue中,父子組件傳遞參數(shù)?props?實(shí)現(xiàn)方式,文章通過(guò)代碼示例介紹的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下2023-07-07
import.meta.glob() 如何導(dǎo)入多個(gè)目錄下的資源(最新推薦)
import.meta.glob() 其實(shí)不僅能接收一個(gè)字符串,還可以接收一個(gè)字符串?dāng)?shù)組,就是匹配多個(gè)位置,本文給大家介紹import.meta.glob() 如何導(dǎo)入多個(gè)目錄下的資源,感興趣的朋友一起看看吧2023-11-11
vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證條
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

