以下示范了 swiper 嵌套,swiper 内使用 scroll-view,自制 tabbar 控制 swiper。
注意要点。swiper 套 swiper 的时候,内部的 swiper 需要加一个 wrap 外层,要不然它的 swiper-item 高度不能达到 100%。
注意踩坑。截至目前的开发者工具版本 v1.01.171013,有一个不知能不能算 Bug 的问题,scroll-view 的第一个子元素如果有 margin-top,即使 scroll-view 内部未满也会导致其抖动。在官方社区发了个帖,然而依旧老样子,官方没人理我。
目前觉得只有一个小遗憾,实机上 swiper 切换时有点卡顿,或者说 transition 的时间稍稍长了点。

let title = ['标题1', '标题2', '标题3'];
Page({
data: {
// index:全局下标 inner:内部滑块下标 outer:外部滑块下标 # 第一个外部滑块里套了两个内部滑块
swiperSelected: { index: 0, inner: 0, outer: 0 },
titleSlider: {
width: 100 / title.length, // 百分比
left: 0
},
text_title: title
},
bindTitleTap: function (e) {
let id = e.currentTarget.dataset.id,
swiperSelected = this.data.swiperSelected,
titleSlider = this.data.titleSlider;
console.info('当前点击:', id);
if (swiperSelected.index !== id) {
swiperSelected.index = id;
if (id < 2) {
// 内部滑块
swiperSelected.inner = id;
swiperSelected.outer = 0;
} else {
// 外部滑块
swiperSelected.outer = 1;
}
titleSlider.left = titleSlider.width * id;
this.setData({
swiperSelected,
titleSlider
});
}
},
forbidSwiperMove: function () {
// 禁止左右滑动
}
});
<view class="weui-flex titles">
<block wx:for="{{text_title}}" wx:key="*this">
<text class="{{index === swiperSelected.index ? 'selected' : ''}}" data-id="{{index}}" bindtap="bindTitleTap">{{item}}</text>
</block>
<view class="title-slider" style="width: {{titleSlider.width}}%; left: {{titleSlider.left}}%;"></view>
</view>
<swiper class="outer" current="{{swiperSelected.outer}}">
<swiper-item class="outer" catchtouchmove="forbidSwiperMove">
<view class="weui-cells">
<view class="weui-cell" hover-class="weui-cell_active">
<view class="weui-cell__bd">共享标题</view>
</view>
</view>
<view class="swiper-wrap">
<swiper class="inner" current="{{swiperSelected.inner}}">
<swiper-item catchtouchmove="forbidSwiperMove">
<scroll-view scroll-y="true" enable-back-to-top="true">
<view class="placeholder"></view>
<view class="weui-cells">
<view class="weui-cell">
<view class="weui-cell__bd">测试1</view>
</view>
</view>
</scroll-view>
</swiper-item>
<swiper-item catchtouchmove="forbidSwiperMove">
<scroll-view scroll-y="true" enable-back-to-top="true">
<view class="placeholder"></view>
<view class="weui-cells">
<view class="weui-cell">
<view class="weui-cell__bd">测试2</view>
</view>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</swiper-item>
<swiper-item class="outer" catchtouchmove="forbidSwiperMove">
<scroll-view scroll-y="true" enable-back-to-top="true">
<view class="placeholder"></view>
<view class="weui-cells">
<view class="weui-cell">
<view class="weui-cell__bd">测试3</view>
</view>
</view>
</scroll-view>
</swiper-item>
</swiper>
.titles {
position: relative;
z-index: 1;
background-color: #fcfcfc;
box-shadow: 0 1px 2px rgba(150, 150, 150, .3);
justify-content: space-around;
}
.titles text {
font-size: 32rpx;
line-height: 80rpx;
box-sizing: border-box;
height: 80rpx;
padding: 0 5px;
text-align: center;
flex: auto;
}
.titles text.selected {
color: #46c01b;
}
.title-slider {
position: absolute;
bottom: 0;
transition: left .5s;
}
.title-slider::after {
position: absolute;
bottom: 0;
left: 50%;
width: 4em;
height: 2px;
margin-left: -2em;
content: '';
background-color: #46c01b;
}
swiper.outer {
height: calc(100vh - 80rpx);
background-color: red;
}
swiper.inner {
position: absolute;
width: 100%;
height: 100%;
background-color: #aaa;
}
swiper-item.outer {
display: flex;
flex-direction: column;
}
scroll-view {
height: 100%;
}
scroll-view .weui-cells {
margin-top: 0;
margin-bottom: 1.17647059em;
}
.swiper-wrap {
position: relative;
flex: auto;
}