我有一个vue TabContiainer组件,可以这样使用它:
<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>
好好干。
这是TabContainer代码:
import { h } from 'vue'
// import './TabContainer.scss' //ignore css
const TabContainer = {
name: 'TabContainer',
props: {
modelValue: {
type: String,
required: true,
},
},
render() {
const slots = this.$slots.default()
console.log(slots)
// check slot type
const existInValidSubCom = slots.some(slot => ![TabHeader, TabContent].includes(slot.type))
if (existInValidSubCom) {
const message = "TabContainer's sub commpont muse be TabHeader and 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>
<!-- some comment -->
<TabContent tab-id="1"> content 1 </TabContent>
<TabContent tab-id="2"> content 2 </TabContent>
<TabContent tab-id="3"> content 3 </TabContent>
</TabContainer>
一些注解导致以下代码在TabContainer中为真
// check slot type
const existInValidSubCom = slots.some(slot => ![TabHeader, TabContent].includes(slot.type))
if (existInValidSubCom) {
const message = "TabContainer's sub commpont muse be TabHeader and TabContent"
// throw new Error(message)
return h('div', message)
}
为什么需要检查子组件类型?与table tag一样,table中允许使用有限的tag,只能使用head tbody tr td。希望vue组件之间有这样的限制或类似的功能。
控制台插槽:
存在一个符号(注解)。
它不会呈现为except。如果我使用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>
插槽具有符号(片段)vnode。
我试图找到一个好的方法来检查vnode或插槽类型。但没有得到一个好的。有什么更好的实现在我的情况下?如何可以得到它修复?
1条答案
按热度按时间r1zhe5dt1#
使用这些代码检查类型。