创建导航栏组件

初始化导航栏

1、准备数据

[
    {
    
     name: 'all', label: '全部订单' },
    {
    
     name: 'unpay', label: '待付款' },
    {
    
     name: 'deliver', label: '待发货' },
    {
    
     name: 'receive', label: '待收货' },
    {
    
     name: 'comment', label: '待评价' },
    {
    
     name: 'complete', label: '已完成' },
    {
    
     name: 'cancel', label: '已取消' }
]

2、组件编写

tab.vue和tab-panel.vue组件准备

使用组件

1、在app.vue中引入组件

<template>
    <tab v-model:activeName="activeName" @update:activeName="changeActiveName">
        <tabPaanel v-for="item in rderStatus" :key="item.name" :label="item.label" :name="item.name">		</tabPaanel>
    </tab>
</template>

<script setup>
import tab from './components/tab.vue'
import tabPaanel from './components/tab-paanel.vue';
import {
    
     reactive, ref } from 'vue'
const activeName = ref('all')
const changeActiveName = (data) => {
    
    
    console.log(data)
}
const rderStatus = reactive([
    {
    
     name: 'all', label: '全部订单' },
    {
    
     name: 'unpay', label: '待付款' },
    {
    
     name: 'deliver', label: '待发货' },
    {
    
     name: 'receive', label: '待收货' },
    {
    
     name: 'comment', label: '待评价' },
    {
    
     name: 'complete', label: '已完成' },
    {
    
     name: 'cancel', label: '已取消' }
])
</script>

<style scoped lang="less"></style>

遍历循环rderStatus中的数据,通过v-model实现双向绑定,当点击其他标签时,当前页面的activeName也会改变

2、编写tab.vue

import {
    
     useVModel } from '@vueuse/core'

export default {
    
    
    name: 'tab',
    props: {
    
    
        activeName: {
    
    
            type: String,
            default: 'all'
        }
    },
     setup(props, {
     
      emit }) {
    
    
        // 接收v-model
        const activeName = useVModel(props, 'activeName', emit)
        const changetab=(Name)=>{
    
    
            activeName.value=Name
        }
        provide('activeName', activeName)
        return {
    
     activeName,changetab }
    },

通过使用useVModel方法,实现组件内数据与父组件数据,双向绑定,当activeName被改变时,会自动调用@update:activeName=“changeActiveName” 这个回调函数,且携带改变后的值

3、通过render()函数渲染页面,在tab.vue的setup函数后编写render()函数

render() {
    
    
    	//拿到tab的slot内容
        const main = this.$slots.default()
        // 动态面板
        const dypanels = []
        // 遍历获取dom节点
        main.forEach(element => {
    
    
            if (element.type.name === 'tabpanel') {
    
    
                console.log(element)
                //    加入dom节点
                dypanels.push(element)
            } else {
    
    
                element.children.forEach(item => {
    
    
                    dypanels.push(item)
                })
            }
        });
        // console.log('dypanels',dypanels)
        // 定义渲染结构
        const nav = (
            // 将数据带入到nav标签中,在jsx中,{}内写的是js语法
            <nav className="nav">
                {
    
    
            		// 将动态面板的数据全部渲染到a标签中,加上click事件 和 选中样式
                    dypanels.map((item,i)=>{
    
    
                        return <a onClick={
    
    ()=>this.changetab(item.props.name)} class={
    
    this.activeName===item.props.name?'active':''}>{
    
    item.props.label}</a>
                    })
                }
            </nav>
        )
        return <div>{
    
    nav}</div>
    }

main的结构如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFneXb6p-1680841949056)(C:\Users\86137\AppData\Local\Temp\1680798818570.png)]

完整的tab.vue


<script lang="jsx">
import {
    
     useVModel } from '@vueuse/core'
import {
    
     provide } from 'vue'
export default {
    
    
    name: 'tab',
    props: {
    
    
        activeName: {
    
    
            type: String,
            default: 'all'
        }
    },
    setup(props, {
     
      emit }) {
    
    
        // 接收v-model

        const activeName = useVModel(props, 'activeName', emit)
        const changetab=(Name)=>{
    
    
            activeName.value=Name
        }
        provide('activeName', activeName)
        return {
    
     activeName,changetab }
    },
    render() {
    
    
        const main = this.$slots.default()
        console.log(main)
        // 动态面板
        const dypanels = []
        // 遍历获取dom节点
        main.forEach(element => {
    
    
            if (element.type.name === 'tabpanel') {
    
    
                console.log(element)
                //    加入dom节点
                dypanels.push(element)
            } else {
    
    
                element.children.forEach(item => {
    
    
                    dypanels.push(item)
                })
            }
        });
        // console.log('dypanels',dypanels)
        // 定义渲染结构
        const nav = (
            <nav className="nav">
                {
    
    
                    dypanels.map((item,i)=>{
    
    
                        return <a onClick={
    
    ()=>this.changetab(item.props.name)} class={
    
    this.activeName===item.props.name?'active':''}>{
    
    item.props.label}</a>
                    })
                }
            </nav>
        )
        return <div>{
    
    nav}</div>
    }
}
</script>

<style scoped lang="less">
.nav{
    
    
    font-size: 20px;
    margin-left: 20px;

    .active{
    
    
        color: red;
    }
}
</style>

3、编写tabpanel.vue

<template>
    <div class="label" v-show="name===activeName">
        <slot></slot>    
    </div>
</template>

<script>
import {
    
     inject } from 'vue';
export default {
    
    
    name:'tabpanel',
    props:{
    
    
        label:{
    
    
            type:String,
            default:''
        },
        name:{
    
    
            type:String,
            default:''
        }
    },
    setup(){
    
    
        const activeName=inject('activeName')
        return {
    
    activeName}
    }
}
</script>

<style scoped lang="less">

</style>

通过tab.vue传过来的activeName来控制tab-panel里面内容的展示

实际应用

在查看订单中,通过切换不同的label标签,用于展示不同的订单,在app。vue中切换activeName,获取对应的订单数据

eName’)
return {activeName}
}
}


通过tab.vue传过来的activeName来控制tab-panel里面内容的展示

# 实际应用

在查看订单中,通过切换不同的label标签,用于展示不同的订单,在app。vue中切换activeName,获取对应的订单数据

猜你喜欢

转载自blog.csdn.net/m0_57108418/article/details/130009460