Vue3 + Less 实现动态圆角 TabBar:从代码到优化实践

在前端开发中,TabBar 是一个非常常见的 UI 组件,而在一些设计需求中,我们希望激活的 Tab 有动态变化的圆角效果,并且宽度可以根据选中状态自适应。本文将分享一个 Vue3 + Less 实现的 TabBar 组件案例,完整分析代码结构、实现思路,并展示优化技巧。

效果预览:

🧩 需求分析

我们希望 TabBar 拥有以下特性:

  1. 动态激活状态 :根据 modelValue 高亮当前 Tab。
  2. 圆角过渡效果:激活 Tab 的上下圆角动态显示。
  3. 自适应宽度:选中 Tab 宽度放大,未选中 Tab 等分。
  4. 复用性强:多种激活形态(左圆角、右圆角、左右圆角)可复用样式。
  5. 响应用户点击:选中状态更新并触发事件。

🛠 组件实现

1️⃣ 模板部分

vue 复制代码
<template>
  <div class="tabbar" :style="{ 'grid-template-columns': getGridFr }">
    <div
      v-for="(it) in tabs"
      :key="it.value"
      :class="{
        'tabbar-item': true,
        'active': modelValue === it.value && modelValue === 'use',
        'active1': modelValue === it.value && modelValue === 'charge',
        'active2': modelValue === it.value && modelValue === 'code',
      }"
      @click="select(it.value)"
    >
      <div class="top"></div>
      {{ it.label }}
    </div>
  </div>
</template>
  • 动态类绑定 :根据不同 Tab 值,使用 active1/active2/active3 控制圆角样式。
  • 网格布局grid-template-columns 根据选中状态动态调整宽度。

样式部分(Less )

less 复制代码
.tabbar {
  display: grid;
  transition: all 0.3s;
  --th: 8px;

  &-item {
    text-align: center;
    height: 40px;
    background-color: var(--el-color-primary);
    color: #fff;
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    user-select: none;
  }

  // ----------- 公共激活样式 -----------
  .active-base() {
    color: var(--el-color-primary);
    background-color: #fff;
    position: relative;
    --bh: 40px;

    .top {
      position: absolute;
      height: var(--th);
      background-color: #fff;
      top: calc(var(--th) * -1);
    }
  }

  // 圆角片段(左右通用)
  .circle(@pos, @clip) {
    display: block;
    content: '';
    position: absolute;
    width: var(--bh);
    height: var(--bh);
    background-color: var(--el-color-primary);
    @{pos}: 0;
    bottom: 0;
    z-index: 1;
    clip-path: @clip;
  }

  // ----------- 各种激活样式 -----------

  // 左右都有圆角
  .active {
    .active-base();

    .top {
      border-radius: 100px 100px 20px 20px;
      width: calc(100% - 80px);
    }

    &::before { .circle(left, ellipse(100% 100% at 0% 0%)); }
    &::after  { .circle(right, ellipse(100% 100% at 100% 0%)); }
  }

  // 右侧圆角
  .active1 {
    .active-base();

    .top {
      border-radius: 0 100px 20px 20px;
      width: calc(100% - 40px);
      left: 0;
    }

    &::after { .circle(right, ellipse(100% 100% at 100% 0%)); }
  }

  // 左侧圆角
  .active2 {
    .active-base();

    .top {
      border-radius: 100px 0 20px 20px;
      width: calc(100% - 40px);
      right: 0;
    }

    &::before { .circle(left, ellipse(100% 100% at 0% 0%)); }
  }
}
相关推荐
Hello--_--World7 分钟前
VUE:逻辑复用
前端·javascript·vue.js
陶甜也23 分钟前
3D智慧城市:blender建模、骨骼、动画、VUE、threeJs引入渲染,飞行视角,涟漪、人物行走
前端·3d·vue·blender·threejs·模型
患得患失94929 分钟前
【前端websocket】企业级功能清单
前端·websocket·网络协议
落魄江湖行29 分钟前
基础篇四 Nuxt4 全局样式与 CSS 模块
前端·css·typescript·nuxt4
禅思院30 分钟前
前端性能优化:从"术"到"道"的完整修炼指南
前端·架构·前端框架
架构师老Y2 小时前
003、Python Web框架深度对比:Django vs Flask vs FastAPI
前端·python·django
小陈工4 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
xiaotao1319 小时前
第九章:Vite API 参考手册
前端·vite·前端打包
午安~婉9 小时前
Electron桌面应用聊天(续)
前端·javascript·electron
彧翎Pro9 小时前
基于 RO1 noetic 配置 robosense Helios 32(速腾) & xsense mti 300
前端·jvm