uni-app(Vue3)实现自定义 Tab 切换滑块效果(微信小程序)

在 uni-app 开发微信小程序时,系统自带的 tabs 组件往往难以满足复杂样式需求,例如:

  • 滑块需要居中对齐文字

  • 滑块宽度自定义

  • 切换时带动画

  • tab 数量动态变化

本文将介绍如何使用 uni-app + Vue3 组合式 API 实现一个自定义 Tab 切换组件,并实现 底部滑块跟随动画效果

一、效果说明

实现功能:

  • Tab 点击切换

  • 当前 tab 高亮

  • 底部滑块平滑移动

  • 滑块始终居中当前文字


二、Tab 结构

html 复制代码
<view class="tab-Con">
  <view class="tabs">
    <view
      v-for="(item, index) in tabsData"
      :key="index"
      class="tab-item"
      :id="'tab' + index"
      :class="{ active: current == index }"
      @click="changeTab(item.id,index)"
    >
      {{ item.petTypeName }}
    </view>

    <!-- 底部滑块 -->
    <view
      class="tab-line"
      :style="{ width: lineWidth + 'rpx', left: lineLeft + 'px' }"
    >
    </view>
  </view>
</view>

说明:

  • 每个 tab 绑定唯一 id:tab0、tab1

  • 滑块通过 left 动态移动

  • 当前激活 tab 通过 active 控制样式


三、数据结构

复制代码
javascript 复制代码
const tabsData = ref([
  { id: 1, petTypeName: "猫猫" },
  { id: 2, petTypeName: "狗狗" }
])

当前选中:

javascript 复制代码
const current = ref(0)
const currentPetType = ref(1)

四、点击切换逻辑

点击 tab 后:

  1. 更新当前选中 index

  2. DOM 更新完成后重新计算滑块位置

javascript 复制代码
const changeTab = (id, index) => {
  currentPetType.value = id
  current.value = index

  // DOM更新后测量
  nextTick(() => {
    updateLine()
  })
}

五、滑块位置计算(核心)

通过 SelectorQuery 获取当前 tab 的位置信息:

javascript 复制代码
const updateLine = () => {
  const index = current.value
  const query = uni.createSelectorQuery().in(instance)

  query.select('#tab' + index)
    .boundingClientRect((rect) => {
      if (rect) {
        // 计算滑块居中
        lineLeft.value = rect.left + rect.width / 2 - lineWidth / 4
      }
    })
    .exec()
}

计算逻辑:

滑块left = tab左边距 + tab宽度一半 - 滑块一半

这样滑块始终居中。


六、样式

css 复制代码
.tab-Con {
  border-bottom: 1px solid #DEE1E6;
  padding: 20rpx 0;
  position: relative;

  .tabs {
    display: flex;
    position: relative;
    width: 100%;
    height: 80rpx;
    justify-content: space-around;
    align-items: center;

    .tab-item {
      font-size: 30rpx;
      color: #565D6D;
      flex: 1;
      text-align: center;
    }

    .tab-item.active {
      color: #000;
      font-weight: bold;
    }

    .tab-line {
      position: absolute;
      bottom: 0;
      height: 4rpx;
      background-color: #000;
      transition: left 0.25s ease;
    }
  }
}

关键点:

复制代码

transition: left 0.25s ease;

实现滑动动画。


七、完整流程

组件运行流程:

  1. 页面加载完成执行 updateLine()

  2. 点击 tab

  3. 更新 current

  4. nextTick 等待 DOM 更新

  5. 重新计算滑块位置

  6. 触发动画滑动


八、总结

本文实现了一种 uni-app 微信小程序自定义 Tab 滑块方案,核心思路:

  • flex 布局实现 tab 排列

  • SelectorQuery 获取 tab 宽度位置

  • 计算滑块居中偏移

  • CSS transition 实现动画

该方案具有:

  • tab 数量可动态扩展

  • 适配不同文字长度

  • 滑块始终精准居中

相关推荐
踩着两条虫1 小时前
从设计稿到代码:VTJ.PRO 的 AI 集成系统架构解析
前端·vue.js·人工智能
codingWhat3 小时前
如何实现一个「万能」的通用打印组件?
前端·javascript·vue.js
徐小夕5 小时前
pxcharts Ultra V2.3更新:多维表一键导出 PDF,渲染兼容性拉满!
vue.js·算法·github
前端Hardy6 小时前
别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
前端·javascript·vue.js
前端Hardy6 小时前
别再让 `console.log` 上线了!它正在悄悄拖垮你的生产系统
前端·javascript·vue.js
青青家的小灰灰6 小时前
从入门到精通:Vue3 ref vs reactive 最佳实践与底层原理
前端·vue.js·面试
OpenTiny社区6 小时前
我的新同事是个AI:支持skill后,它用TinyVue搭项目还挺溜!
前端·vue.js·ai编程
李剑一6 小时前
大屏天气展示太普通?视觉升级!用 Canvas 做动态天气遮罩,雷阵雨效果直接封神
前端·vue.js·canvas
本末倒置1837 小时前
面向 Vue 开发者的 Next.js 快速入门指南
前端·vue.js
滕青山7 小时前
文本字符数统计 在线工具核心JS实现
前端·javascript·vue.js