Vue在渲染函数createELement和JSX中使用插槽slot
Vue對于插槽有兩個專門的APIvm.$slots和vm.$scopedSlots,分別是普通插槽和作用域插槽,使用JSX語法或渲染函數的時候,定義插槽將使用上述兩個API。
渲染函數createElement
普通插槽和作用域插槽在定義上相差不大,但是在使用方法上略微有點區別,詳見渲染函數>數據對象
普通插槽,插槽內容以children子節點形式,然后在數據對象中指定插槽名
// 定義帶插槽的組件,`$slots.default`為匿名插槽,其余的則是具名插槽,匿名插槽的插槽名可以省略 const MySlot = {render (h) {return h('div', [h('header', [this.$slots.header]),h('main', [this.$slots.header]),h('footer', [this.$slots.footer])])} }// 在`children子節點`中指定插槽名以使用具名插槽,未指定插槽名的則放入匿名插槽中 export default {components: { MySlot },render (h) {return h('MySlot', [h('template', { slot: 'header' }, 'hello world'),'children node',h('div', { slot: 'footer' }, 'this is footer')])} }作用域插槽,與普通插槽不同,作用域插槽的內容直接放入渲染函數的數據對象中的
// 定義作用域插槽 const MySlot = {data () {return { user: 'John', content: 'vue', copytight: 'CopyRight' }},render (h) {return h('div', [h('header', [this.$scopedSlots.header({ user: this.user })]),h('main', [this.$scopedSlots.default({ content: this.content })]),h('footer', [this.$scopedSlots.footer({ copytight: this.copytight })])])} }// 要使用作用域插槽的數據內容,則插槽必須在組件的數據對象`scopedSlots`中使用,如`header`所示 // 作用域插槽也可以當作普通插槽使用,如`default`和`footer` export default {components: { MySlot },render (h) {return h('MySlot', {scopedSlots: {header: props => `hello, ${props.user}`}}, ['children node',h('div', { slot: 'footer' }, 'this is footer')])} }關于靜態插槽和作用域插槽:
你可以通過 this.$slots 訪問靜態插槽的內容,每個插槽都是一個 VNode 數組
也可以通過 this.$scopedSlots 訪問作用域插槽,每個作用域插槽都是一個返回若干 VNode 的函數
this.$slots 返回的是數組,this.$scopedSlots 返回的是函數,這里踩一個坑,使用 this.$scopedSlots 定義的插槽如果未被使用則會報錯
例如刪除或注釋掉具名插槽footer內容后,控制臺報錯
[Vue warn]: Error in render: "TypeError: this.$scopedSlots.footer is not a function"如何避免這個問題暫時沒有找到解決方案,研究還不夠深入
2021年1月25日補充:
使用 this.$scopedSlots 定義的插槽如果未被使用則會報錯
原因: 以footer插槽為例,其實不用想的太復雜,作用域插槽this.$scopedSlots.footer()就是一個函數,MySlot組件使用了這個函數,但是父組件卻沒有傳入此函數的定義,所以MySlot再調用這個函數的時候發生報錯。
解決辦法: 在MySlot調用this.$scopedSlots.footer()前進行一次判斷此函數是否存在即可。
JSX語法
JSX是createElement的語法糖,在用法上沒有什么區別,對照著上面的內容稍微改一改就好了
靜態插槽
const MySlot = {render (h) {return (<div><header>{this.$slots.header}</header><main>{this.$slots.default}</main><footer>{this.$slots.footer}</footer></div>)} }export default {render (h) {return (<MySlot><template slot='header'>hello world</template>children node<div slot='footer'>this is footer</div></MySlot>)} }作用域插槽
const MySlot = {data () {return { user: 'John', content: 'vue', copytight: 'CopyRight' }},render (h) {return (<div><header>{this.$scopedSlots.header({ user: this.user })}</header><main>{this.$scopedSlots.default({ content: this.content })}</main><footer>{this.$scopedSlots.footer({ copytight: this.copytight })}</footer></div>)} }export default {render (h) {return (<MySlotscopedSlots={{header: props => `hello, ${props.user}`}}>children node<div slot='footer'>this is footer</div></MySlot>)} }總結
以上是生活随笔為你收集整理的Vue在渲染函数createELement和JSX中使用插槽slot的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue-router和react-rou
- 下一篇: vue完全编程方式与react在书写和运