vue3+ts实现自定义按钮导航

效果图

点击对应按钮,相应按钮被激活,背景平移至激活按钮,字体高亮,其余按钮重置,由于ele没有类似tab,就简单记录下。
在这里插入图片描述

实现

<template>
  <div class="tab_wrapper">
    <span
      v-for="item in showTabList"
      :key="item.value"
      ref="tabItemRefList"
      class="tab-item"
      :class="{ 'active-tab': modelValue === item.value }"
      @click="handleChange(item.value)"
      >{{ item.label }}</span
    >
    <span class="animate-tab" :style="{ width: `${activeWidth}px`, left: `${activeLeft}px` }" />
  </div>
</template>
<script setup lang="ts">
  import { computed, nextTick, ref, watch } from 'vue';
  import _ from 'lodash';
  interface buttonTabType {
  value: string;
  label: string;
}
  const props = defineProps({
    tabList: {
      type: Array<buttonTabType>,
      default: () => [],
    },
    modelValue: {
      type: [String, Number, Boolean],
      default: undefined,
    },
  });
  const emits = defineEmits(['update:modelValue', 'change']);
  const showTabList = computed(() => {
    return props.tabList;
  });
  const tabItemRefList = ref<any>([]); // 激活的索引位置
  const activeTabIndex = computed(() =>
    _.findIndex(showTabList.value, (item) => item.value === props.modelValue),
  );
  const activeLeft = ref(0); //激活的距离左边位置
  const activeWidth = ref(0); //激活的宽度

  watch(
    activeTabIndex,
    () => {
      nextTick(() => {
        activeLeft.value = tabItemRefList.value[activeTabIndex.value]?.offsetLeft || 0;
        activeWidth.value = tabItemRefList.value[activeTabIndex.value]?.offsetWidth || 0;
      });
    },
    { flush: 'post', immediate: true },
  );
  const handleChange = (value) => {
    if (value === props.modelValue) return;
    emits('update:modelValue', value);
    emits('change', value);
  };
</script>
<style scoped lang="scss">
  .tab_wrapper {
    background: #f3f4f8;
    display: inline-block;
    height: 32px;
    font-size: 12px;
    overflow: hidden;
    border-radius: 2px;
    position: relative;
    border: 1px solid #eaebee;
    .tab-item {
      height: 30px;
      display: inline-block;
      line-height: 30px;
      padding: 0 16px;
      color: #a4a4a4;
      cursor: pointer;
      position: relative;
      z-index: 1;
      transition: color 300ms ease 0s;
      &.active-tab {
        color: #3b68f0;
        box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1);
      }
    }
    .animate-tab {
      height: 32px;
      display: inline-block;
      border-radius: 2px;
      background: #fff;
      position: absolute;
      z-index: 0;
      transition: all 300ms ease 0s;
      box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1);
    }
  }
</style>

使用

<buttonTab v-model="activeTab" :tab-list="chartTabList" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿乐今天敲代码没

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

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

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

打赏作者

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

抵扣说明:

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

余额充值