微信小程序-导航栏+滑动翻页

最近在做一个微信小程序的项目,中间遇到一个需求,需要用一个顶部的导航栏显示商品分类,点击可以切换下方的商品列表,下方商品列表也可以滑动翻页

效果

效果图

思路

实现的几个要点

  • scroll-view > view来做导航栏
  • swiper > swiper-item > scroll-view > view的方式来做下方显示内容的区域
  • js动态控制导航栏的滚动位置,使选中项居中显示
  • 根据屏幕大小调整swiper的大小,使页面不会滚动,但下方的scroll-view会滚动
  • 通过对上方scroll-view和下方swiper响应事件的处理来实现翻页功能

界面中各个元素所使用的组件如下图所示

分析

代码

index.wxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<view class="container" enable-flex="true">
<!-- 导航栏 -->
<scroll-view class="navbar" scroll-x="true"
scroll-left="{{scrollLeft}}" scroll-with-animation="true">
<view
wx:for="{{navbarItem}}" wx:key="{{index}}"
class="navbar-item {{current==index ? 'navbar-item-active' : ''}}"
data-navbarindex="{{index}}" bindtap="onNavBarTap">
{{item}}
</view>
</scroll-view>

<!-- 列表 -->
<swiper
class="swiper-box"
bindchange="onSwiperChange"
duration="300"
current="{{current}}"
style="height: {{winHeight-150}}rpx;">
<swiper-item class="list" wx:for="{{navbarItem}}" wx:key="index">
<scroll-view class="list" scroll-y="true">
<view class="list-item">
<text>{{item}}</text>
</view>
<view class="list-item">
<text>{{item}}</text>
</view>
<view class="list-item">
<text>{{item}}</text>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>

index.wxss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
page {
background-color: #efefef;
}
.container {
display: flex;
flex-direction: column;
align-items: left;
box-sizing: border-box;
}

/* 导航栏 */
.navbar {
height: 50rpx;
background-color: #fff;
white-space:nowrap;
font-size: 36rpx;
}
.navbar-item {
padding: 0rpx 20rpx;
display: inline;
}
.navbar-item-active {
color: #0080ff;
border-bottom: 1px solid #0080ff;
}

/* 内容列表 */
.swiper-box {
display: block;
margin-top: 5rpx;
}
.list {
height: 100%;
}
.list-item {
height: 600rpx;
background-color: pink;
border: 1px solid #000;
}

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
const app = getApp()

Page({
data: {
navbarItem: {
0: "类型0",
1: "类型1",
2: "类型2",
3: "类型3",
4: "类型4",
5: "类型5",
6: "类型6",
7: "类型7",
8: "类型8",
9: "类型9",
10: "类型10",
11: "类型11",
},
current: 0,
winHeight: 0, // 窗口高度
scrollLeft: 0, // 距离左边的距离
winWidth: 0, // 屏幕的宽
},

onLoad: function () {
var that = this;
wx.getSystemInfo({
success: function (res) {
var clientHeight = res.windowHeight,
clientWidth = res.windowWidth,
rpxR = 750 / clientWidth;
var calc = clientHeight * rpxR;
that.setData({
winHeight: calc,
winWidth: clientWidth
});
}
});
},

/**
* 点击切换当前分类
*/
onNavBarTap: function (e) {
var current = e.currentTarget.dataset.navbarindex;
this.setData({
current: current
});
this.adjustNavbar();
},

/**
* 滑动切换当前分类
*/
onSwiperChange: function (e) {
this.setData({
current: e.detail.current
});
this.adjustNavbar();
},

/**
* 调整 navbar 选中项的位置
*/
adjustNavbar: function () {
var self = this;
const query = wx.createSelectorQuery()
query.selectAll(".navbar-item").boundingClientRect();
query.exec(function (res) {
var num = 0;
for (var i = 0; i < self.data.current; i++) {
num += res[0][i].width
}
self.setData({
scrollLeft: Math.ceil(num - 100)
})
});
}
})