Weapp影视评分项目开发(16):搜索页的实现(下)swiper 结合 scroll-view 实现滑动 tab 页
前言
本篇是搜索页实现的下篇,主要讲解如何使用 swiper 结合 scroll-view 标签实现 tab 页的滑动切换效果。
知识点
swiper 结合 scroll-view 实现 tab 页滑动切换
一、功能介绍
因为搜索结果有影视、影人、角色三种类型,目前微信小程序的 swiper 中嵌套 scroll-view 的效果还不错,兼容层面的 bug 基本解决了,所以我对原来的点击 tab 切换的效果做了升级,现在内容可滑动切换的方式,以带来更好的用户体验。
二、 效果预览
![Weapp影视评分项目开发(16):搜索页的实现(下)swiper 结合 scroll-view 实现滑动 tab 页](https://img.blogweb.cn/article/012217e051da4970be01f70cd8942877.webp)
三、效果实现
1. 页面布局
页面布局部分之前有提到过,搜索结果对应的组件为 search-result
,我们要做的是把内容部分占满。
需要注意的是,
swiper
与scroll-view
组件都需要设置高度,否则两个都会使用默认值,且swiper
的高度不会被内容(这里的内容是scroll-view
标签)自动撑满。
布局主要代码如下:
<view class="result-list">
<!-- swiper 组件,我们需要监听它的 change 值的改变,使上方菜单与其对应 -->
<!-- swiper 需要设置高度把页面撑满,因为上方高度为 166rpx,所以此处高度为 calc(100vh - 166rpx) -->
<swiper class="swiper" bindchange="handleSwiper" current="{{current}}">
<!-- 此处的 swiper-item 可以使用 wx:for 循环处理,为方便理解,未使用 -->
<swiper-item>
<!-- 滚动标签的使用,设置为 y 轴滚动 -->
<!-- 我们需要监听滚动触底事件,以加载更多内容 -->
<scroll-view class="scroll-view" scroll-y bindscrolltolower="handleReachBottom">
<movie-item wx:for="{{movies}}" movie="{{item}}" wx:key="id" />
</scroll-view>
</swiper-item>
<!-- 影人 -->
<swiper-item>
<scroll-view class="scroll-view" scroll-y bindscrolltolower="handleReachBottom">
<actor-item wx:for="{{actors}}" actor="{{item}}" wx:key="id" />
</scroll-view>
</swiper-item>
<!-- 角色代码略 -->
</swiper>
</view>
注意:
以上代码中,swiper-item
标签可以使用 wx:for
循环来处理,为便于理解,此处直接写了两个 swiper-item
标签。为简化代码,角色部分代码、加载动画、触底提示、无数据提示等内容移除了,可以按需要在每个内容区域增加对应的代码。
样式代码:
.result-list {
padding-top: 74rpx;
.swiper, .scroll-view {
/* 不设置高度不会被内容撑开 */
/* 高度需要设置为屏幕剩余区域高度 */
height: calc(100vh - 166rpx);
}
}
2. 逻辑交互
上一篇我们讲了查询接口请求相关的实现,本篇关于接口查询部分的代码就不再赘述,主要讲一下 swiper
切换与 tab
直接是如何显示对应的,以及变更后的数据结构信息。
1) 如何初始化数据结构
因为查询有三种类型,所以我们将其定义为了一个数组对象,这样既方便模板渲染时直接使用循环展示内容,又方便数据初始化设置,即使后期需要添加其它类型,也只需要在类型数组中增加相应属性即可。
data: {
current: 0, // swiper 当前索引
tabList: [] // 默认类型数组
},
attached() {
this.initData(); // 进入时初始化类型数据结构
},
methods: {
initData() {
// 类型默认数据
const tabList = [
{
name: "影视", // tab 显示的名称
type: "movie", // type 类型,接口查询时使用
loading: false, // 该类型是否在查询状态,用于显示查询加载动画
page: 1, // 当前结果页码
list: [], // 当前查询影视列表
noMoreData: false, // 数据是否显示完
total: 0, // 查询结果条数
}
// 为简化代码,影人、角色信息初始化方式被移除
];
this.setData({
tabList // 初始化数据结构
})
}
}
当变更查询关键字时,我们需要重置数据结构为默认值,这时就可以调用以上的 initData
方法:
watch: {
keyword(val) {
if (val) {
this.refreshSearch(); // 有查询关键字变更
}
}
},
// 重置数据结构并发起接口查询
refreshSearch() {
this.initData();
this.doSearch();
}
2) swiper 事件与 tab 切换关联
上面的模板中,我们监听了 swiper
的 bindchange
事件,该事件会返回一个 current
值,为当前 swiper-item
的索引值,我们可以根据该值来设置对应的 tab
值:
// swiper 切换时改变对应类型
handleSwiper({ detail }) {
const current = e.detail
const type = this.data.tabList[current].type; // 获取当前类型
this.typeChange(type);
},
// 类型切换时改变对应 swiper 索引
typeChange(e) {
// 当 tab 切换时,我们需要取消上次接口请求,
// 否则上次类型的请求结果会放入本次类型的结果中
if (this.data.cancel) {
this.data.cancel.abort();
this.data.cancel = null;
}
// tab 切换有两种情况,第一种是点击上方的 tab 类型
// 否则是由 handleSwiper 方法中传入 type 值进行调用
const type = e.currentTarget ? e.currentTarget.dataset.type : e;
const current = this.data.tabList.findIndex(t => t.type === type); // 当前类型对应索引
this.setData({
current // tab 类型切换需要改变 swiper 显示为对应项
})
}
3) 查询结果设置
因为类型是一个数组,所以我们接口查询出对应数据时,需要做对应数组的内容改变,这时我们可以使用以下方法:
const {code, data, total } = response; // 接口返回结果伪代码
const index = this.data.tabList.findIndex(t => t.type === this.data.type);
const tab = this.data.tabList[index];
// 以下方式设置要变更的 key 值
const list_key = 'tabList[' + index + '].list';
const page_key = 'tabList[' + index + '].page';
const total_key = 'tabList[' + index + '].total';
this.setData({
[list_key]: tab.list.concat(data), // 合并新增数据
[page_key]: ++tab.page,
[total_key]: total
})
最后
本篇我们已经将搜索页面的主要内容介绍完毕,它是日常业务中常用到的一个页面,一般情况下业务不会比这个复杂,其中最重要的是网络请求取消方法的使用。 下一篇,我们将开始讲解项目中最复杂的一个页面——影视详情页的实现。
转载自:https://juejin.cn/post/7176661503720816697