Vue高級組件之函數(shù)式組件的使用場景與源碼分析
介紹
Vue提供了一種可以讓組件變?yōu)闊o狀態(tài)、無實(shí)例的函數(shù)化組件。從原理上說,一般子組件都會(huì)經(jīng)過實(shí)例化的過程,而單純的函數(shù)組件并沒有這個(gè)過程,它可以簡單理解為一個(gè)中間層,只處理數(shù)據(jù),不創(chuàng)建實(shí)例,也是由于這個(gè)行為,它的渲染開銷會(huì)低很多。實(shí)際的應(yīng)用場景是,當(dāng)我們需要在多個(gè)組件中選擇一個(gè)來代為渲染,或者在將children,props,data等數(shù)據(jù)傳遞給子組件前進(jìn)行數(shù)據(jù)處理時(shí),我們都可以用函數(shù)式組件來完成,它本質(zhì)上也是對組件的一個(gè)外部包裝。
使用場景
定義兩個(gè)組件對象,test1,test2
var test1 = { props: ['msg'], render: function (createElement, context) { return createElement('h1', this.msg) } } var test2 = { props: ['msg'], render: function (createElement, context) { return createElement('h2', this.msg) } }
定義一個(gè)函數(shù)式組件,它會(huì)根據(jù)計(jì)算結(jié)果選擇其中一個(gè)組件進(jìn)行選項(xiàng)
Vue.component('test3', { // 函數(shù)式組件的標(biāo)志 functional設(shè)置為true functional: true, props: ['msg'], render: function (createElement, context) { var get = function() { return test1 } return createElement(get(), context) } })
函數(shù)式組件的使用
<test3 :msg="msg" id="test"> </test3> new Vue({ el: '#app', data: { msg: 'test' } })
最終渲染的結(jié)果為:
<h2>test</h2>
源碼分析
函數(shù)式組件會(huì)在組件的對象定義中,將functional屬性設(shè)置為true,這個(gè)屬性是區(qū)別普通組件和函數(shù)式組件的關(guān)鍵。同樣的在遇到子組件占位符時(shí),會(huì)進(jìn)入createComponent進(jìn)行子組件Vnode的創(chuàng)建。由于functional屬性的存在,代碼會(huì)進(jìn)入函數(shù)式組件的分支中,并返回createFunctionalComponent調(diào)用的結(jié)果。 注意,執(zhí)行完createFunctionalComponent后,后續(xù)創(chuàng)建子Vnode的邏輯不會(huì)執(zhí)行,這也是之后在創(chuàng)建真實(shí)節(jié)點(diǎn)過程中不會(huì)有子Vnode去實(shí)例化子組件的原因。(無實(shí)例)
function createComponent(){ ··· if (isTrue(Ctor.options.functional)) { return createFunctionalComponent(Ctor, propsData, data, context, children) } }
createFunctionalComponent方法會(huì)對傳入的數(shù)據(jù)進(jìn)行檢測和合并,實(shí)例化FunctionalRenderContext,最終調(diào)用函數(shù)式組件自定義的render方法執(zhí)行渲染過程。
function createFunctionalComponent( Ctor, // 函數(shù)式組件構(gòu)造器 propsData, // 傳入組件的props data, // 占位符組件傳入的attr屬性 context, // vue實(shí)例 children// 子節(jié)點(diǎn) ){ // 數(shù)據(jù)檢測合并 var options = Ctor.options; var props = {}; var propOptions = options.props; if (isDef(propOptions)) { for (var key in propOptions) { props[key] = validateProp(key, propOptions, propsData || emptyObject); } } else { // 合并attrs if (isDef(data.attrs)) { mergeProps(props, data.attrs); } // 合并props if (isDef(data.props)) { mergeProps(props, data.props); } } var renderContext = new FunctionalRenderContext(data,props,children,contextVm,Ctor); // 調(diào)用函數(shù)式組件中自定的render函數(shù) var vnode = options.render.call(null, renderContext._c, renderContext) }
而FunctionalRenderContext這個(gè)類最終的目的是定義一個(gè)和真實(shí)組件渲染不同的render方法。
function FunctionalRenderContext() { // 省略其他邏輯 this._c = function (a, b, c, d) { return createElement(contextVm, a, b, c, d, needNormalization); }; }
執(zhí)行render函數(shù)的過程,又會(huì)遞歸調(diào)用createElement的方法,這時(shí)的組件已經(jīng)是真實(shí)的組件,開始執(zhí)行正常的組件掛載流程。
問題:為什么函數(shù)式組件需要定義一個(gè)不同的createElement方法?- 函數(shù)式組件createElement和以往唯一的不同是,最后一個(gè)參數(shù)的不同,之前章節(jié)有說到,createElement會(huì)根據(jù)最后一個(gè)參數(shù)決定是否對子Vnode進(jìn)行拍平,一般情況下,children編譯生成結(jié)果都是Vnode類型,只有函數(shù)式組件比較特殊,它可以返回一個(gè)數(shù)組,這時(shí)候拍平就是有必要的。我們看下面的例子:
Vue.component('test', { functional: true, render: function (createElement, context) { return context.slots().default } }) <test> <p>slot1</p> <p>slot</p> </test>
此時(shí)函數(shù)式組件test的render函數(shù)返回的是兩個(gè)slot的Vnode,它是以數(shù)組的形式存在的,這就是需要拍平的場景。
簡單總結(jié)一下函數(shù)式組件,從源碼中可以看出,函數(shù)式組件并不會(huì)像普通組件那樣有實(shí)例化組件的過程,因此包括組件的生命周期,組件的數(shù)據(jù)管理這些過程都沒有,它只會(huì)原封不動(dòng)的接收傳遞給組件的數(shù)據(jù)做處理,并渲染需要的內(nèi)容。因此作為純粹的函數(shù)可以也大大降低渲染的開銷。
總結(jié)
到此這篇關(guān)于Vue高級組件之函數(shù)式組件的使用場景與源碼分析的文章就介紹到這了,更多相關(guān)Vue高級組件之函數(shù)式組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue19 組建 Vue.extend component、組件模版、動(dòng)態(tài)組件 的實(shí)例代碼
這篇文章主要介紹了vue19 組建 Vue.extend component、組件模版、動(dòng)態(tài)組件 的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04Vue實(shí)現(xiàn)Base64轉(zhuǎn)png、jpg圖片格式
這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)Base64轉(zhuǎn)png、jpg圖片格式的相關(guān)資料,前段獲取生成的是base64圖片,需要轉(zhuǎn)化為jpg,png,需要的朋友可以參考下2023-09-09Vue 中如何將函數(shù)作為 props 傳遞給組件的實(shí)現(xiàn)代碼
這篇文章主要介紹了Vue 中如何將函數(shù)作為 props 傳遞給組件的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Vue 對象和數(shù)據(jù)的強(qiáng)制更新方式
這篇文章主要介紹了Vue 對象和數(shù)據(jù)的強(qiáng)制更新方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue-router鉤子函數(shù)實(shí)現(xiàn)路由守衛(wèi)
這篇文章主要介紹了vue-router鉤子函數(shù)實(shí)現(xiàn)路由守衛(wèi),對vue感興趣的同學(xué),可以參考下2021-04-04vue使用vue-json-viewer展示JSON數(shù)據(jù)的詳細(xì)步驟
最近在開發(fā)一個(gè)公司的投放管理系統(tǒng)的操作日志模塊,要查看某條操作日志的請求參數(shù),要將請求的參數(shù)以JSON格式的形式展示出來,下面這篇文章主要給大家介紹了vue使用vue-json-viewer展示JSON數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2022-09-09vue3引入uview-plus3.0移動(dòng)組件庫的流程
這篇文章主要介紹了vue3引入uview-plus3.0移動(dòng)組件庫的流程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06Vue3.0數(shù)據(jù)響應(yīng)式原理詳解
這篇文章主要介紹了Vue3.0數(shù)據(jù)響應(yīng)式原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10