开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
前言
本篇将实现 “正在热映” 与 “即将上映” 两个页面模块,他们很相似,都是整屏的列表页,在这两个页面中,我们将首次使用计算属性 computed、使用官方 api 实现下拉刷新与上拉加载更多功能。
知识点
computed 的使用 下拉刷新 上拉加载 position: sticky 1px 边框
一、影视信息卡组件的实现
上一篇我们详细介绍了 movie-row 组件的实现,movie-item 组件与它很像,所以这一篇,我们不再将它如何实现,而是介绍下这个组件需要注意的地方。
1. 组件预览
2. flex 弹性布局
该组件使用 flex 实现左右布局,左侧为海报区域固定宽度 164rpx,右侧为内容区域,宽度为 flex: 1 弹性。此时如果 flex 区域内容的宽度超出 calc(750rpx - 164rpx - 60rpx) (即去除左边海报区域,两侧外边距)宽度时,海报区域的宽度将会被压缩,这是因为 flex 的默认收缩规则为 flex-shrink: 1; ,我们将其收缩规则改为 flex-shrink: 0; 即可。
主要代码如下:
<!-- components/movie/movie-item/index.wxml -->
<!-- 内置的下边框 m-hairline--bottom -->
<view class="movie-item m-hairline--bottom">
<view class="movie-item__poster"></view>
<view class="movie-item__content"></view>
<view>
/* components/movie/movie-item/index.scss */
.movie-item {
display: flex;
flex-shrink: 0; /* 设置收缩规则 */
margin: 0 30rpx;
.movie-item__poster {
width: 164rpx
}
.movie-item__content {
flex: 1;
}
}
3. 1px 边框的使用
mind-ui-weapp 组件库内置了 Retina 屏下的 1px 边框,之前的文章中已在 app.scss 文件中引入了该样式文件,信息卡的下边框只需要在外层元素添加 m-hairline--bottom 样式属性即可。
二、列表页面的实现
1. 效果预览
下拉刷新与上拉加载:
1. computed 属性的使用
之前在 第04篇三方组件的使用中,我们介绍过 computed 组件的安装与使用,在这次的“即将上映”页面,我们将正式使用它来实现影视按日期分组的需求。
需求:“即将上映”的接口分页返回的数据,会按照上映时间排序,每个影视字段中会有一个 release_date (上映时间)字段,我们需要将日期相同的影视放在一个分组中,结构如下:
如果没有 computed 属性,我们一般在获取到数据后,写个函数将数组转成需要的格式,有了 computed 后,处理变的便捷了很多,我们无需在数据返回后使用函数处理数据,把数据交给 computed 去自动处理:
// pages/movie/coming/index.js
Page({
behaviors: [wx.computedBehavior], // 引入 computed 属性支持
data: {
list: [], // 影视信息列表
}
computed: {
// 将影视按日期分组,注意 computed 中无法使用 this,需要把 data 作为参数传入
groups(data) {
let groups = [];
data.list.map((movie) => {
const gLen = groups.length;
if (gLen && movie.release_date === groups[gLen - 1].date) {
groups[gLen - 1].children.push(movie);
} else {
const group = {
date: movie.release_date,
children: [movie],
};
groups.push(group);
}
});
return groups;
}
}
})
<!--pages/movie/coming/index.wxml -->
<view class="main">
<view class="group m-hairline--bottom" wx:for="{{groups}}" wx:for-item="group" wx:key="date">
<view class="group-title">{{ group.date }}</view>
<view class="group-children">
<movie-item wx:for="{{group.children}}" wx:key="id" movie="{{item}}" is-coming />
</view>
</view>
</view>
2. position: sticky 属性的使用
以上的 group-title 属性的元素,滚动到顶部时会有吸顶效果,我们日常项目中,也经常有这样的需求,早前我们需要用监听滚动距离的方式,给元素添加 position: fixed 属性使其固定在某个位置,现在我们只需要几行 css 属性就可以实现,他就是 position: sticky ,我们通过 caniuse 网站查看该属性的浏览器支持度已经很高了(在不支持的浏览器中,大多设备老旧,性能较低,js 实现的方式不会很流畅,算是优雅降级吧)。代码如下:
.group-title {
z-index: 1;
position: sticky;
top: 0;
padding: 0 30rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
font-weight: bold;
background-color: #fff;
}
三、上拉加载
1. 上拉加载的实现
上拉加载是移动端实现分页能力的常用方式,在 web 端我们一般通过监听页面滚动距离,如果滚动距离 - 页面高度的值在一定范围内,则调用接口获取下一页的数据。微信小程序替我们封装好了这一些判定条件与方法,它提供了一个名为 onReachBottom 方法用于监听用户上拉触底事件,我们只需要在事件触发后调用接口即可。
以“即将上映”实现为例:
// pages/movie/coming/index.js
import { getMovieComing } from "../../../api/api"; // 引入接口
Page({
data: {
loading: false, // 接口请求状态
movies: [], // 影视列表
page: 1, // 当前页
per_page: 20, // 每页条数
total: 0, // 总条数
},
onLoad() {
this.getMovieComing();
},
// 获取即将上映影视列表
async getMovieComing() {
if(this.data.loading) return; // 防止上拉加载重复请求
this.loading = true;
const params = {
page: this.data.page,
per_page: this.data.per_page,
}
// ES6 对象解构语法,未使用 try catch 是因为接口层做了处理,失败也会有返回值不中断执行
const { code, data, total } = await getMovieComing(params);
if(code === 200) {
this.setData({
movies: [...this.data.movies, ...data], // 使用 ES6 展开运算符将下一页数据添加到原有列表中
})
this.data.page++; // 页码+1
}
this.loading = false; // 关闭加载状态
},
// 页面触底
onReachBottom() {
this.getMovieComing();
},
})
触底距离使用默认的50像素即可,无需在
.json文件中设置
四、下拉刷新
小程序使用下拉刷新功能非常便捷,只需要一个配置 + 2个方法即可实现:
1. 开启下拉刷新配置:
// coming/index.json
{
"enablePullDownRefresh": true
}
2. 下拉刷新的两个方法:
wx.startPullDownRefresh(); // 调用后将触发下拉刷新动画,效果与用户手动下拉刷新一致
wx.stopPullDownRefresh(); // 关闭下拉刷新动画
3. 使用
日常业务中,开启下拉刷新配置后,我们需要在接口获取到数据后关闭下拉刷新动画;开启下拉刷新方法很少使用,业务场景是被当做页面初始进入时的加载动画。
如果是列表页有分页的场景,wx.startPullDownRefresh() 方法建议放在 onLoad 方法中,并在调用接口前使用,如果放在接口中调用就需要判断当前分页是否为第一页了,增加代码冗余,示例如下:
Page({
// data 代码同上
onLoad() {
wx.startPullDownRefresh(); // 开启下拉刷新动画
this.getMovieComing();
},
// 下拉刷新事件,需要重置列表中的数据为初始值
onPullDownRefresh() {
this.setData({
movie: [],
page: 1,
total: 0,
})
this.getMovieComing();
},
// 其它代码同上
async getMovieComing() {
// 省略部分代码
const { code, data, total } = await getMovieComing(params);
// 当接口请求完成后,无论是成功还是失败,都需要调用以下方法关闭下拉刷新动画
wx.stopPullDownRefresh();
}
})
总结
本篇文章主要介绍了 computed 的引入与使用,以及上拉加载与下拉刷新功能。因为这刷新与加载两个功能在项目中使用处特别多,下一篇我将会扩展 Page 属性,并将下拉刷新与上拉加载代码封装到 mixins 文件中。