vue实现的tabs标签组件

入口文件

<template>
  <div v-cloak>
    <tabs v-model="value">
    <pane label="标签一" name="1">
      标签一内容
    </pane>
     <pane label="标签二" name="2">
      标签二内容
    </pane>
     <pane label="标签三" name="3">
      标签三内容
    </pane>
  </tabs>
  </div>
</template>
<script>
import Tabs from '../components/tabs/tabs'
import pane from '../components/tabs/tab'
export default {
  components: {
    Tabs,
    pane
  },
  data () {
    return {
      value: '1'
    }
  }
}
</script>

tabs组件

<template>
<div class="tabs">
  <div class="tabs-bar">
  <!--标签页标题,通过v-for实现循环--!>
    <div :class="tabCls(item)"
          v-for="(item,index) in navList"
        @click = "handleChange(index)" :key="item.name">
    {{item.label}}
    </div>
  </div>
  <div class="tabs-content">
  <!--slot放置pane组件内容--!>
    <slot></slot>
  </div>
</div>
</template>

<script>
export default {
  name: 'Tabs',
  props: {
    value: [String, Number],
    required: true
  },
  data () {
    return {
      currentValue: this.value,
      navList: []
    }
  },
  methods: {
    tabCls (item) {
      return [
        'tabs-tab',
        {
          'tabs-tab-active': item.name === this.currentValue
        }
      ]
    },
    getTabs () {
    //获取pane
      return this.$children.filter(function (item) {
        return item.$options.name === 'pane'
      })
    },
    updateNav () {
    //获取标题,name,并放置到navList数组中
      this.navList = []
      let _this = this
      this.getTabs().forEach(function (pane, index) {
        _this.navList.push({
          label: pane.label,
          name: pane.name || index

        })
        if (!pane.name) pane.name = index
        if (index === 0) {
          if (!_this.currentValue) {
            _this.currentValue = pane.name || index
          }
        }
      })
      this.updateStatus()
    },
    updateStatus () {
      let tabs = this.getTabs()
      let _this = this
      tabs.forEach(function (tab) {
        let b = tab.name === _this.currentValue
        tab.show = b
        return tab.show
      })
    },
    handleChange (index) {
      let nav = this.navList[index]
      let name = nav.name
      this.currentValue = name
      this.$emit('input', name)
      this.$emit('on-click', name)
    }
  },
  watch: {
    value: function (val) {
      this.currentValue = val
    },
    currentValue () {
      this.updateStatus()
    }
  }
}
</script>

<style  scoped>
[v-cloak]{
    display: none;
}
.tabs{
    font-size: 14px;
    color: #657180;
}
.tabs-bar:after{
    content: '';
    display: block;
    width: 100%;
    height: 1px;
    background: #d7dde4;
    margin-top:-1px;
}
.tabs-tab{
    display: inline-block;
    padding: 4px 16px;
    margin-right: 6px;
    background: #fff;
    border: 1px solid #d7dde4;
    cursor: pointer;
    position: relative;
}
.tabs-tab-active{
    color: #3399ff;
    border-top: 1px solid #3399ff;
    border-bottom: 1px solid #3399ff;
}
.tabs-tab-active:before{
    content: '';
    display: block;
    height: 1px;
    background: #3399ff;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}
.tabs-content{
    padding: 8px 0;
}
</style>

pane组件

<template>
  <div class="pane" v-show="show">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'pane',
  props: {
    name: {
      type: String
    },
    label: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      show: true
    }
  },
  methods: {
    updateNav () {
      this.$parent.updateNav()
    }
  },
  watch: {
    label () {
      this.updateNav()
    }
  },
  mounted () {
    this.updateNav()
  },
  computed: {
    active () {
      return false
    }
  }
}
</script>
<style  scoped>
</style>

效果如下图:
这里写图片描述

vue3动态组件实现tabs标签页的步骤如下: 1. 创建tabs组件,包含tabstab两个子组件tabs组件负责显示当前选中的tab和切换tabtab组件则负责显示tab的内容。 2. 在tabs组件中定义一个数组,用于存储所有的tab信息。每个tab信息包括tab的名称和对应的组件。 3. 在tabs组件中使用v-for指令循环渲染所有的tab,同时使用动态组件来渲染对应的组件。 4. 在tab组件中定义一个插槽,用于显示tab的内容。 5. 在tabs组件中定义一个方法,用于切换tab。该方法接受一个index参数,表示要切换到的tab的索引。该方法根据索引更新当前选中的tab,并将对应的组件渲染出来。 6. 在tabs组件中使用v-on指令绑定点击事件,调用切换tab的方法。 7. 在父组件中引入tabs组件,并传入所有的tab信息。 8. 使用tabs组件来显示tab标签页。 示例代码如下: // Tabs.vue <template> <div class="tabs"> <div class="tab-list"> <div class="tab" v-for="(tab, index) in tabs" :key="tab.name" :class="{ active: isActiveTab(index) }" @click="selectTab(index)" >{{ tab.name }}</div> </div> <div class="tab-content"> <component :is="tabs[currentTab].component"></component> </div> </div> </template> <script> export default { name: "Tabs", props: ["tabs"], data() { return { currentTab: 0, }; }, methods: { isActiveTab(index) { return this.currentTab === index; }, selectTab(index) { this.currentTab = index; }, }, }; </script> // Tab.vue <template> <div class="tab-content"> <slot></slot> </div> </template> // App.vue <template> <div class="app"> <Tabs :tabs="tabs"></Tabs> </div> </template> <script> import Tabs from "./Tabs.vue"; import Tab from "./Tab.vue"; import Tab1 from "./Tab1.vue"; import Tab2 from "./Tab2.vue"; export default { name: "App", components: { Tabs, Tab, Tab1, Tab2, }, data() { return { tabs: [ { name: "Tab 1", component: "Tab1" }, { name: "Tab 2", component: "Tab2" }, ], }; }, }; </script>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端岚枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值