在 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 后:
-
更新当前选中 index
-
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;
实现滑动动画。
七、完整流程
组件运行流程:
-
页面加载完成执行
updateLine() -
点击 tab
-
更新 current
-
nextTick 等待 DOM 更新
-
重新计算滑块位置
-
触发动画滑动
八、总结
本文实现了一种 uni-app 微信小程序自定义 Tab 滑块方案,核心思路:
-
flex 布局实现 tab 排列
-
SelectorQuery 获取 tab 宽度位置
-
计算滑块居中偏移
-
CSS transition 实现动画
该方案具有:
-
tab 数量可动态扩展
-
适配不同文字长度
-
滑块始终精准居中