vue3中的render函數(shù)里定義插槽和使用插槽
render函數(shù)里定義插槽和使用插槽
vue3中this.slots和vue2的區(qū)別
vue3:this.slots是一個{ [name: string]: (…args: any[]) => Array | undefined }的對象,每個具名插槽的內容都要通過函數(shù)調用。如v-slot:foo插槽分發(fā)的內容通過this.slots.foo( )返回
vue2:this.slots是一個{ [name: string]: ?Array }的對象,v-slot:foo的內容通過this.slots.foo來訪問 , 而this.scopedSlots才是和vue3里的this.$slots作用一樣.
定義插槽
this.$slots.[插槽名] 這個一個返回VNode數(shù)組的函數(shù),用于訪問靜態(tài)插槽內容.
const BlogPost = defineComponent({
render(){
return h('div', [
h('h1',this.$slots.header&&this.$slots.header()||'默認header插槽'),
h('p',this.$slots.default&&this.$slots.default({message:'我是作用域插槽的message'})||'默認default插槽'),
h('h4',this.$slots.footer&&this.$slots.footer()||'默認footer插槽'),
])
}
})
// 以上代碼相當于以下的template <template> <div> <h1> <slot name="header">默認header插槽</slot> </h1> <p> <slot>默認default插槽</slot> </p> <h4> <slot name="footer">默認footer插槽</slot> </h4> </div> </template>
定義有插槽的組件使用插槽
在h函數(shù)的第三個參數(shù)中使用{ [name: string]: (…args: any[]) => Array | undefined }形式的對象來定義組件的具體插槽內容
const BlogPostWrapper = defineComponent({
? render(){
? ? return h('div',
? ? ? ? ? ? ?{style:'background:skyblue'},
? ? ? ? ? ? ?h(
? ? ? ?? ??? ??? ?BlogPost,
? ? ? ? ? ? ? ??? ?null,
? ? ? ? ? ? ? ??? ?{
? ? ? ? ? ? ? ? ? header(props){
? ? ? ? ? ? ? ? ? ? return '我是傳進的header插槽內容'
? ? ? ? ? ? ? ? ? },
? ? ? ?? ??? ??? ? ?default(props){
? ? ? ?? ??? ??? ? ?// 這里的props就是作用域插槽的插槽prop
? ? ? ? ? ? ? ? ? ? return 'BlogPostWrapper的default插槽內容::>>'+props.message
? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? footer(props){
? ? ? ? ? ? ? ? ? ? return '我是傳進的footer插槽內容'
? ? ? ? ? ? ? ? ? }
? ? ?? ??? ??? ?}
? ? ?? ??? ?)
? ? ? ? ? )
? ?? ?}
})// 相當于template
<template>
?? ?<div>
?? ??? ?<BlogPost>
?? ??? ??? ?<tempalte #header>'我是傳進的header插槽內容'</tempalte>
?? ??? ??? ?<tempalte #default="props">
?? ??? ??? ??? ?{{'BlogPostWrapper的default插槽內容::>>'+props.message}}
?? ??? ??? ?</tempalte>
?? ??? ??? ?<tempalte #footer>我是傳進的footer插槽內容</tempalte>
?? ??? ?</BlogPost>
?? ?</div>
</template>vue3 render函數(shù)小變動
Render function API?是不是感覺有點陌生?那恭喜你,這個改動不會對你這位 <template> 用戶造成影響。
老規(guī)矩,上帝視角看一下:
h需要從全局導入進來(不再是 render 函數(shù)的參數(shù)了)render函數(shù)的參數(shù)改變了(為了在常規(guī)組件和函數(shù)組件中表現(xiàn)一致)VNodes具備了扁平的屬性結構
render函數(shù)的參數(shù)
2.x 這么寫
在 Vue 2.x 的版本中,render 函數(shù)會以參數(shù)的形式自動接收 h 函數(shù)(aka:createElement):
export default {
render(h) {
return h('div');
}
}3.x 應該這么寫
在即將到來的 Vue 3.x 版本中,h 函數(shù)需要手動從全局引入進來:
import { h } from 'vue';
export default {
render() {
return h('div');
}
}render函數(shù)簽名
2.x 這么寫
上面也提到了,2.x 的 render 函數(shù)會自動接收 h 作為參數(shù):
export default {
render(h) {
return h('div');
}
}3.x 應該這么寫
在 3.x 版本中,render 函數(shù)不再接收任何參數(shù)了,它僅存的主要作用就是在 setup 函數(shù)中使用。這樣方便獲取作用域鏈中的響應式狀態(tài)以及各種函數(shù),當然了,也方便獲取任何傳遞給 setup 函數(shù)的參數(shù)。
import { h, reactive } from 'vue';
export default {
setup(props, { slots, attrs, emit }) {
const state = reactive({ count: 0 });
function increment() {
state.count++
}
// 返回一個 render 函數(shù)
return () => {
h(
'div',
{ onClick: increment, },
state.count,
)
}
}
}VNode屬性格式
2.x 是這樣的
domProps 是 VNode 屬性中的一個“嵌套列表”:
{
class: ['button', 'confirm-button'],
style: { color: 'red' },
attrs: { id: 'confirm' },
domProps: { innerHTML: '' },
on: { click: confirmCreate },
key: 'submit-button',
}3.x 中則是這樣的
在 3.x 版本中,VNode 的所有屬性都已經實現(xiàn)了“扁平化”的處理:
{
class: ['button', 'confirm-button'],
style: { color: 'red' },
id: 'submit',
innerHTML: '',
onClick: confirmCreate,
key: 'submit-button',
}其實我也很少用 render 函數(shù),畢竟 template 還是蠻香的。
如果想要獲得更多的詳細信息,請去這里:v3.vuejs.org/guide/migration/render-function-api.html(目前還沒有中文版)
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

