Vue如何检查子组件类型

TabsDemo.vue组件

<template>
    <Tabs>
        <Tab title="导航1">内容1</Tab>
        <Tab title="导航2">内容2</Tab>
    </Tabs>
</template>
<script lang="ts">
import Tabs from '../lib/Tabs.vue'    
import Tab from '../lib/Tab.vue'
export default {
    components: {
        Tabs,
        Tab
    }
}
</script>

Tab.vue

<template>
    <div>Tab 组件</div>
</template>

Tabs.vue

<template>
    <div>Tabs 组件</div>
</template>

1、检查Tabs组件中子组件Tab的类型

Tabs.vue

<template>
    <div>Tabs 组件</div>
</template>
<script lang="ts">
export default {
    setup(props,context){    //组件信息包含在context中
       console.log({...context})
    }
}
</script>
1.png

打印出插槽中slots.default()方法,能看到传入两个节点内容

 setup(props,context){    //组件信息包含在context中
           console.log({...context.slots.default()})
        }
2.png

这里打印出来0和1分别代表TabsDemo中传入的Tab两个节点,分别打印出这两个节点出来

setup(props,context){
       console.log({...context.slots.default()[0]})
       console.log({...context.slots.default()[1]})
    }
3.png

这里显示一堆东西其实是一个虚拟节点东西,我们将它显示在页面中出来的就是我们需要的Tab组件内容。

Tabs组件:

<template>
    <div>
        Tabs 组件
        <component :is="defaults[0]"></component>
        <component :is="defaults[1]"></component>
    </div>
</template>
<script lang="ts">
export default {
    setup(props,context){
      const defaults=context.slots.default()
       return{defaults}
    }
}
</script>
4.png

刚刚说打印出来的虚拟节点中有个type类型,如果说这个类型和我们Tab相等,说明传入的标签就是一个Tab标签。

<script lang="ts">
import Tab from './Tab.vue'
export default {
    setup(props,context){
       const defaults=context.slots.default()
       console.log(defaults[0].type === Tab)    //判断标签是否为Tab  
       return{defaults}
    }
}
</script>
6.png

2、当我们修改成传入标签是div时,检查的类型是错误的。

TabsDemo.vue组件:

<template>
    <Tabs>
        <div title="导航1">内容1</div>
        <div title="导航2">内容2</div>
    </Tabs>
</template>
7.png

3、如何提示让Tabs子标签必须是Tab组件

Tabs组件:

<template>
    <div>
        Tabs 组件
        <component :is="defaults[0]"></component>
        <component :is="defaults[1]"></component>
    </div>
</template>
<script lang="ts">
import Tab from './Tab.vue'
export default {
    setup(props,context){
       const defaults=context.slots.default()
       defaults.forEach((tag)=>{
            if(tag.type !== Tab){     //判断是否Tab类型
                throw new Error('Tab 子标签必须是 Tab')
            }
       })
       return{defaults}
    }
}
</script>

当我们修改成传入标签是div时,打印出一个错误信息,要求我们传入子标签是Tab组件,这叫预防性编程。

TabsDemo.vue组件:

<template>
    <Tabs>
        <div title="导航1">内容1</div>
        <div title="导航2">内容2</div>
    </Tabs>
</template>
8.png

推荐阅读更多精彩内容