1、首先安装@vueuse/core
npm i @vueuse/core -s
2、新建tabs.vue,其内容为:
<script>
import { useVModel } from '@vueuse/core'
import { provide } from 'vue'
export default {
name: 'tabs',
props: {
modelValue: {
type: [String, Number],
default: ''
}
},
setup (props, { emit }) {
const activeName = useVModel(props, 'modelValue', emit)
const tabClick = (name, index) => {
activeName.value = name
emit('tab-click', { name, index })
}
provide('activeName', activeName)
return { activeName, tabClick }
},
render () {
const panels = this.$slots.default()
const dynamicPanels = []
console.log('panels.length', panels.length)
panels.forEach((item) => {
console.log('item', item)
console.log('item.type.name', item.type.name)
if (item.type.name === 'XtxTabsPanel') {
dynamicPanels.push(item)
} else {
item.children.forEach((item) => {
dynamicPanels.push(item)
})
}
})
console.log('dynamicPanels.length', dynamicPanels.length)
console.log('dynamicPanels', dynamicPanels)
const nav = (
<nav>
{dynamicPanels.map((item, i) => {
return (
<a
onClick={() => this.tabClick(item.props.name, i)}
class={{ active: item.props.name === this.activeName }}
href="javascript:;"
>
{item.props.label}
</a>
)
})}
</nav>
)
console.log('nav', nav)
return <div class="tabs">{[nav, dynamicPanels]}</div>
}
}
</script>
<style scoped lang="less">
.tabs {
background: #fff;
> nav {
height: 60px;
line-height: 60px;
display: flex;
border-bottom: 1px solid #f5f5f5;
> a {
text-decoration: none;
width: 110px;
border-right: 1px solid #f5f5f5;
text-align: center;
font-size: 16px;
&.active {
border-bottom: 2px solid lightseagreen;
height: 60px;
background: #fff;
line-height: 56px;
}
}
}
}
</style>
3、新建panels.vue,其内容为:
<template>
<div class="tabs-panel" v-show="name===activeName">
<slot />
</div>
</template>
<script>
import { inject } from 'vue'
export default {
name: 'panels',
props: {
label: {
type: String,
default: ''
},
name: {
type: [String, Number],
default: ''
}
},
setup () {
const activeName = inject('activeName')
return { activeName }
}
}
</script>
4、在APP.vue中使用:
<template>
<tabs v-model="activeName" @tab-click="tabClick">
<panels
v-for="item in orderStatus"
:key="item.name"
:label="item.label"
:name="item.name"
>
{{item.label}}的内容
</panels>
</tabs>
</template>
<script setup>
import tabs from '@/components/tabs.vue'
import panels from '@/components/panels.vue'
import { ref } from 'vue'
const activeName = ref('all')
const orderStatus = [
{ name: 'all', label: '全部订单' },
{ name: 'unpay', label: '待付款' },
{ name: 'deliver', label: '待发货' },
{ name: 'receive', label: '待收货' },
{ name: 'comment', label: '待评价' },
{ name: 'complete', label: '已完成' },
{ name: 'cancel', label: '已取消' }
]
const tabClick = ({ index }) => {
console.log('index', index)
}
</script>
<style scoped lang="less">
</style>
5、显示的效果如下: