網(wǎng)站建設(shè)seo優(yōu)化推廣銷(xiāo)售網(wǎng)絡(luò)平臺(tái)推廣
渲染函數(shù)
官網(wǎng)地址:
https://cn.vuejs.org/guide/extras/render-function
推薦先看一下vue官方的渲染機(jī)制:
https://cn.vuejs.org/guide/extras/rendering-mechanism.html
一、渲染函數(shù)的核心概念與應(yīng)用場(chǎng)景
1.1 為什么需要渲染函數(shù)?
- 模板的局限性:雖然模板語(yǔ)法直觀易用,但在處理高度動(dòng)態(tài)的渲染邏輯(如根據(jù)數(shù)據(jù)結(jié)構(gòu)動(dòng)態(tài)生成組件樹(shù))或封裝可復(fù)用的高級(jí)組件(如表單生成器、可視化編輯器)時(shí),模板的靈活性會(huì)受限。
- 性能與底層控制:渲染函數(shù)直接操作虛擬 DOM(VNode),避免模板編譯開(kāi)銷(xiāo),適合高頻更新場(chǎng)景,同時(shí)能實(shí)現(xiàn)模板無(wú)法完成的底層 DOM 控制。
1.2 渲染函數(shù)與 Vue 版本的關(guān)系
- Vue 2:h函數(shù)是Vue.extend和模板編譯的底層實(shí)現(xiàn),通過(guò)render選項(xiàng)使用。
- Vue 3:h函數(shù)是 Composition API 中render函數(shù)的基礎(chǔ),配合setup函數(shù)使用更靈活,且優(yōu)化了 VNode 結(jié)構(gòu)和 diff 算法。
二、深入理解 h 函數(shù):創(chuàng)建虛擬節(jié)點(diǎn)的核心工具
2.1 創(chuàng)建Vnodes
vue提供了一個(gè)h()
函數(shù)創(chuàng)建vnodes
import {h} from 'vue'const vnode = h(type, // 必選:節(jié)點(diǎn)類(lèi)型(HTML標(biāo)簽/組件/函數(shù))[propsOrChildren], // 可選:屬性對(duì)象或子節(jié)點(diǎn)[children] // 可選:子節(jié)點(diǎn)(當(dāng)?shù)诙€(gè)參數(shù)為屬性時(shí))
)
- type
- HTML 標(biāo)簽:h(‘div’)、h(‘button’)
- 組件對(duì)象:
import MyComponent from './MyComponent.vue'; h(MyComponent)
- 函數(shù):返回 VNode 的函數(shù),如h(() => h(‘span’, ‘動(dòng)態(tài)節(jié)點(diǎn)’))
- propsOrChildren
- 屬性對(duì)象:包含 DOM 特性、組件 Prop、事件等,如
{ id: 'box', class: 'container' }
- 子節(jié)點(diǎn)(字符串 / 數(shù)組):當(dāng)省略屬性時(shí),第二個(gè)參數(shù)為子節(jié)點(diǎn),如
h('div', '文本內(nèi)容')
- 屬性對(duì)象:包含 DOM 特性、組件 Prop、事件等,如
- children
- 支持嵌套 VNode 數(shù)組,如
h('div', null, [h('p', '段落1'), h('p', '段落2')])
- 支持嵌套 VNode 數(shù)組,如
2. 2 h函數(shù)的使用
-
除了類(lèi)型必填以外,其他的參數(shù)都是可選的
h('div') h('div', { id: 'foo' })
-
attribute 和 property 都能在 prop 中書(shū)寫(xiě)
https://www.doubao.com/thread/w0b21c1cca8c7e48ch('div', { class: 'bar', innerHTML: 'hello' })
-
像
.prop
和.attr
這樣的的屬性修飾符,可以分別通過(guò).
和^
前綴來(lái)添加h('div', { '.name': 'some-name', '^width': '100' })
-
類(lèi)與樣式可以像在模板中一樣,用數(shù)組或?qū)ο蟮男问綍?shū)寫(xiě)
h('div', { class: [foo, { bar }], style: { color: 'red' } })
-
事件監(jiān)聽(tīng)器應(yīng)以 onXxx 的形式書(shū)寫(xiě)
h('div', { onClick: () => {} })
-
children 可以是一個(gè)字符串
h('div', { id: 'foo' }, 'hello')
-
沒(méi)有 props 時(shí)可以省略不寫(xiě)
h('div', 'hello') h('div', [h('span', 'hello')])
-
children 數(shù)組可以同時(shí)包含 vnodes 與字符串
h('div', ['hello', h('span', 'hello')])
類(lèi)與樣式的靈活寫(xiě)法
const isActive = true
const size = 'large'h('div', {// 類(lèi)名支持?jǐn)?shù)組/對(duì)象組合class: ['container',{ 'active': isActive },{ [`size-${size}`]: size }],// 樣式支持對(duì)象/字符串style: {color: 'red',fontSize: '16px',...(isActive ? { fontWeight: 'bold' } : {})}
})
Fragment 支持(Vue 3 特有)
Fragment 是一種虛擬 DOM 概念,簡(jiǎn)單說(shuō)就是允許組件返回多個(gè)根節(jié)點(diǎn)(虛擬節(jié)點(diǎn),VNode ),而無(wú)需用一個(gè)額外標(biāo)簽包裹 。
// 返回多個(gè)節(jié)點(diǎn)(自動(dòng)包裹在Fragment中)
h('div', [h('h1', '標(biāo)題'),h('p', '內(nèi)容1'),h('p', '內(nèi)容2')
])
三、props 深入:渲染函數(shù)中的數(shù)據(jù)傳遞機(jī)制
props 是用于描述虛擬節(jié)點(diǎn)對(duì)應(yīng)的 DOM 元素或組件的屬性、事件等信息的對(duì)象
3.1 props 的本質(zhì)與作用
- 組件通信橋梁:在渲染函數(shù)中,props是父組件向子組件傳遞數(shù)據(jù)的對(duì)象,等價(jià)于模板中的v-bind屬性綁定。
- 類(lèi)型安全:通過(guò)聲明props的類(lèi)型、默認(rèn)值和必填項(xiàng),實(shí)現(xiàn)數(shù)據(jù)校驗(yàn),提升組件健壯性。
3.2 在渲染函數(shù)中使用 props
- 3.2.1 傳遞 props 給組件
import ChildComponent from './ChildComponent.vue'// 父組件中用h函數(shù)傳遞props
h(ChildComponent, {title: '子組件標(biāo)題',count: 10,user: { name: '張三', age: 25 },onUpdate: (val) => console.log('更新值:', val)
})
- 3.2.2 子組件聲明 props(Vue 3 示例)
<template><div><h3>{{ title }}</h3><p>用戶:{{ user.name }} ({{ user.age }})</p></div>
</template><script setup>
import { defineProps } from 'vue'// 聲明props(對(duì)象形式)
const props = defineProps({title: {type: String,default: '默認(rèn)標(biāo)題'},count: {type: Number,required: true},user: {type: Object,default: () => ({ name: '未知', age: 0 })}
})
</script>
3.3 屬性修飾符:精準(zhǔn)控制 prop 與 attribute
- .prop修飾符(明確作為組件 prop)
// 子組件聲明props: { name: String }
h(ChildComponent, { '.name': '李四' // 等價(jià)于模板中的:name="李四"
})
- ^attr修飾符(明確作為 DOM attribute)
// 渲染為<div data-id="123"></div>
h('div', { '^data-id': '123' // 強(qiáng)制作為HTML attribute
})// 給組件的根元素添加attribute(即使組件未聲明該prop)
h(ChildComponent, { '^data-role': 'admin' // 會(huì)出現(xiàn)在組件根元素的DOM上
})
四、實(shí)戰(zhàn)案例:渲染函數(shù)與 props 的組合應(yīng)用
4.1 動(dòng)態(tài)生成表單組件
import { h, ref } from 'vue'// 表單字段配置
const fields = [{ type: 'text', label: '姓名', model: 'name' },{ type: 'number', label: '年齡', model: 'age' },{ type: 'checkbox', label: '同意協(xié)議', model: 'agreed' }
]// 表單數(shù)據(jù)
const formData = ref({name: '張三',age: 25,agreed: false
})// 渲染函數(shù)
export default {setup() {return () => h('form', { class: 'dynamic-form' }, [// 循環(huán)生成表單項(xiàng)fields.map(field => h('div', { class: 'form-group' }, [h('label', null, field.label),h('input', {type: field.type,id: field.model,value: formData.value[field.model],onChange: (e) => {formData.value[field.model] = field.type === 'checkbox' ? e.target.checked : e.target.value}})]),// 提交按鈕h('button', { type: 'submit',class: 'btn-primary',onClick: (e) => {e.preventDefault()console.log('表單提交:', formData.value)}}, '提交')])}
}
4.2 高階組件(HOC)封裝
import { h } from 'vue'// 權(quán)限驗(yàn)證HOC
const withAuth = (Component) => {return {setup() {const isAuthenticated = ref(false)// 模擬權(quán)限驗(yàn)證setTimeout(() => {isAuthenticated.value = true // 假設(shè)驗(yàn)證通過(guò)}, 1000)return () => isAuthenticated.value ? h(Component) // 有權(quán)限時(shí)渲染組件: h('div', { class: 'auth-error' }, '無(wú)訪問(wèn)權(quán)限')}}
}// 使用HOC
const ProtectedComponent = withAuth({setup() {return () => h('div', '受保護(hù)的內(nèi)容')}
})// 渲染HOC組件
h(ProtectedComponent)
五、性能優(yōu)化與最佳實(shí)踐
5.1 合理使用 key 提升 diff 效率
// 列表渲染時(shí)指定key
h('ul', null, list.map(item => h('li', { key: item.id }, item.text))
)
5.2 避免過(guò)度使用渲染函數(shù)
- 優(yōu)先模板:模板語(yǔ)法足以滿足需求時(shí),避免強(qiáng)行使用渲染函數(shù),保持代碼可讀性。
- 組件封裝:將復(fù)雜渲染邏輯封裝為組件,通過(guò) props 和事件暴露接口,而非在單個(gè)組件中堆砌渲染函數(shù)。
5.3 結(jié)合 JSX 提升開(kāi)發(fā)效率
// 需要配置Babel/TS支持JSX
import { h } from 'vue'
const app = () => (<div class="app"><h1>JSX標(biāo)題</h1><button onClick={() => alert('點(diǎn)擊')}>操作按鈕</button><ChildComponent :count={10} /></div>
)
六、Vue 2 與 Vue 3 中渲染函數(shù)的差異
七、總結(jié):渲染函數(shù)的適用場(chǎng)景與學(xué)習(xí)建議
7.1 推薦使用場(chǎng)景
-
動(dòng)態(tài)組件生成:根據(jù) API 數(shù)據(jù)動(dòng)態(tài)決定組件結(jié)構(gòu)(如表單生成器、可視化編輯器)。
-
高階組件封裝:實(shí)現(xiàn)權(quán)限控制、加載狀態(tài)等通用邏輯的復(fù)用。
-
性能敏感場(chǎng)景:高頻更新的列表或圖表組件,避免模板編譯開(kāi)銷(xiāo)。
一般不使用h函數(shù),大多數(shù)情況下,當(dāng)我們使用的第三方庫(kù)不滿足我們需要的api時(shí),但是有需要對(duì)其樣式進(jìn)行修改,可以使用h函數(shù)動(dòng)態(tài)修改