目前在微信小程序中并没有官方的 tab 页前端组件,但是这类需求却经常会出现在实际的项目中,所以我们需要自己来实现出这种效果。下面先看示例效果图,顺便想想实现方案:

这里我写出我的实现方法,可以滑动的 tab 页面使用 swiper 组件,tab 按钮就随便用个 view 容器就是了,tab 按钮下方的页面指示线条我也用个 1px 高度的有色背景 view 来实现;点击 tab 按钮切换 tab 页的相关事件肯定要有,指示线条的动画效果准备结合 CSS3 的过渡效果与 swiper 组件的 bindchange 事件实现,因为弄这种动画需要进行位置上的计算,所以实际上指示线条的宽度我也弄成了根据 tab 按钮的宽度动态计算的。
wxml 部位代码:
<view class="VIEW_tabs_box">
<view class="VIEW_tab_button" bind:tap="selectTab" data-index="0">Tab1</view>
<view class="VIEW_tab_button" bind:tap="selectTab" data-index="1">Tab2</view>
<view class="VIEW_tab_button" bind:tap="selectTab" data-index="2">Tab3</view>
</view>
<view class="VIEW_tabs_indicate_line" style="width:{{indicateLineWidth}}px;transform:translateX({{indicateLineTranslateX}}px);"></view>
<swiper bindchange="SWIPER_page_changed" model:current="{{currentPage}}">
<swiper-item class="SWIPER_ITEM_pages">Page1</swiper-item>
<swiper-item class="SWIPER_ITEM_pages">Page2</swiper-item>
<swiper-item class="SWIPER_ITEM_pages">Page3</swiper-item>
</swiper>
wxss 部位代码:
.VIEW_tabs_box {
display: flex;
justify-content: space-around;
}
.VIEW_tab_button {
display: inline-block;
width: 100%;
padding: 10px;
text-align: center;
}
.VIEW_tabs_indicate_line {
height: 1px;
background: #00f;
transition: all .5s;
}
.SWIPER_ITEM_pages {
padding: 10px;
box-sizing: border-box;
background: #eaeaea;
}
js 部位代码:
Page({
data: {
indicateLineWidth: 0,
indicateLineTranslateX: 0,
currentPage: 0,
tabWidth: 0
},
onLoad(options) {
var that = this
const windowInfo = wx.getWindowInfo()
// 页面载入时动态计算出 tab 按钮的宽度、tab 页指示线条的宽度与其所在的位置偏移量
var tabWidth = windowInfo.windowWidth / 3
var indicateLineWidth = tabWidth / 2
var indicateLineTranslateX = tabWidth / 2 - indicateLineWidth / 2 + that.data.currentPage * tabWidth
that.setData({
indicateLineWidth,
indicateLineTranslateX,
tabWidth
})
},
SWIPER_page_changed(e) {
var that = this
// 每当 swiper 的当前页属性改变时就刷新 tab 页指示线条的位置偏移
var currentPage = e.detail.current
var indicateLineTranslateX = that.data.tabWidth / 2 - that.data.indicateLineWidth / 2 + currentPage * that.data.tabWidth
that.setData({
indicateLineTranslateX
})
},
selectTab(e) {
var that = this
// 在点击 tab 按钮时变更 swiper 的当前页属性
var pageIndex = e.currentTarget.dataset.index
that.setData({
currentPage: pageIndex
})
}
})
结语:还可以监听 swiper 组件的滑动过渡事件以实现更精致的 tab 页指示条动画效果,比如实现跟随 tab 页滑动而进行实时动画效果的指示条动画,不过不建议在微信小程序渲染模式为 webview 时这样做,这样做可能会感到卡顿、不流畅;微信小程序推出了 skyline 渲染模式,可以对用户界面和程序脚本分开渲染,这样就可以解决这一问题并实现更为精致复杂的动画效果,但是 skyline 渲染模式目前并不完善,有兴趣的网友可以自行研究。