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" />

猜你喜欢

转载自blog.csdn.net/qq_45840993/article/details/128661628
今日推荐