vue中如何便捷的判断vnode的类型?

我有一个组件,使用方式如下:

<TabContainer v-model="activeTab">

<TabHeader tab-id="1"> tab1 </TabHeader>

<TabHeader tab-id="2"> tab2 </TabHeader>

<TabHeader tab-id="3"> tab3 </TabHeader>

<TabContent tab-id="1"> content 1 </TabContent>

<TabContent tab-id="2"> content 2 </TabContent>

<TabContent tab-id="3"> content 3 </TabContent>

</TabContainer>

按照预期工作。

实现如下:

import { h } from 'vue'

import './TabContainer.scss'

const TabContainer = {

name: 'TabContainer',

props: {

modelValue: {

type: String,

required: true,

},

},

render() {

const slots = this.$slots.default()

console.log(slots)

// 检查子组件类型

const existInValidSubCom = slots.some(slot => ![TabHeader, TabContent].includes(slot.type))

if (existInValidSubCom) {

const message = 'TabContainer的子组件必须是 TabHeader 和 TabContent'

// throw new Error(message)

return h('div', message)

}

const Tabs = slots

.filter(item => item.type === TabHeader)

.map(Tab =>

h(Tab, {

class: {

tab: true,

active: Tab.props['tab-id'] === this.modelValue,

},

onClick: () => {

this.$emit('update:modelValue', Tab.props['tab-id'])

},

}),

)

const content = slots.find(

slot => slot.type === TabContent && slot.props['tab-id'] === this.modelValue,

)

return [h('div', { class: 'tab-container' }, Tabs), h('div', content)]

},

}

export default TabContainer

export const TabHeader = TabItem({ name: 'TabHeader' })

export const TabContent = TabItem({ name: 'TabContent' })

function TabItem(options) {

return {

...options,

props: {

tabId: {

type: String,

required: true,

},

},

render() {

return h('div', null, this.$slots.default())

},

}

}

当插槽里有注释时:

<TabContainer v-model="activeTab">

<TabHeader tab-id="1"> tab1 </TabHeader>

<TabHeader tab-id="2"> tab2 </TabHeader>

<TabHeader tab-id="3"> tab3 </TabHeader>

<!-- 注释 -->

<TabContent tab-id="1"> content 1 </TabContent>

<TabContent tab-id="2"> content 2 </TabContent>

<TabContent tab-id="3"> content 3 </TabContent>

</TabContainer>

slots 多了一个注释的 vnode:

vue中如何便捷的判断vnode的类型?

下面的判断条件结果为 true,组件不能按照预期工作:

 // 检查子组件类型

const existInValidSubCom = slots.some(slot => ![TabHeader, TabContent].includes(slot.type))

当有很多TabHeader和 TabContent 时,希望使用v-for

<TabContainer v-model="activeTab">

<TabHeader :tab-id="item" v-for="(item, index) in ['1', '2', '3']" :key="index">

tab{{ item }}

</TabHeader>

<TabContent tab-id="1"> content 1 </TabContent>

<TabContent tab-id="2"> content 2 </TabContent>

<TabContent tab-id="3"> content 3 </TabContent>

</TabContainer>

slots 里多了一个 Symbol(Fragement)

vue中如何便捷的判断vnode的类型?

也导致刚才的判断结果为 true。

vue 版本:^3.2.41

这种情况该如何处理比较好?或者说,有什么快捷的函数可判断一个vnode的类型呢?


回答:

1.用组件的名字来比较,而不是直接的组件对象。你可以用 vnode.type.name 来拿到组件的名字:

const existInValidSubCom = slots.some(slot => ![TabHeader.name, TabContent.name].includes(slot.type?.name))

在处理 slots:

const existInValidSubCom = slots.some(slot => {

if (slot.type === Comment || slot.type === Fragment) {

return false;

}

return ![TabHeader.name, TabContent.name].includes(slot.type?.name);

});

以上是 vue中如何便捷的判断vnode的类型? 的全部内容, 来源链接: utcz.com/p/933178.html

回到顶部