@Tabs切换 + 分页加载
Tabs切换效果图
正在加载效果图
没有更多效果图
@uView组件使用
uView/Tabs的使用
uView/Tabs文档 先搂一眼!
uView/loadMore的使用
uView/loadMore文档先搂一眼!
@准备工作
电影条目组件封装
components/FilmItem.vue
<template>
<!-- 点击跳转详情页 -->
<view
class="item"
@click="toDetail(item.filmId)">
<view class="left">
<image
:src="item.poster"
alt=""
mode="widthFix" />
</view>
<view class="middle">
<view>
<text class="name">{{ item.name }}</text>
<text class="dimension">{{ item.filmType.name }}</text>
</view>
<view>
观众评分
<text class="grade">{{ item.grade }}</text>
</view>
<view class="actors"> 主演:{{ item.actors.map(({ name }) => name).join(" ") }} </view>
<view>{{ item.nation }} | {{ item.runtime }}分钟</view>
</view>
<view class="right">
<button
class="ticket"
v-show="isOnShow || item.isPresale">
{{ isOnShow ? "购票" : "预购" }}
</button>
</view>
</view>
</template>
<script>
export default {
props: ["item", "isOnShow"],
methods: {
/* 跳转详情页 */
toDetail(filmId) {
console.log("toDetail", filmId);
// 跳转页面
uni.navigateTo({
url: `/pages/sub/detail/detail?filmid=${filmId}`,
});
},
},
};
</script>
<style lang="scss">...</style>
没有更多组件封装
components/NoMoreItem.vue
<template>
<view class="wrapper"> -无更多电影- </view>
</template>
<script></script>
<style>
.wrapper {
background-color: #eee;
color: #bdc0c5;
height: 100rpx;
line-height: 100rpx;
text-align: center;
font-size: 0.8rem;
}
</style>
电影列表组件封装
- 这个组件符合 easy-com 规范,页面模板可以直接使用!
components/my-film-list/my-film-list.vue
<template>
<view class="wrapper">
<!-- <text>正在热映</text> -->
<!-- <text>{{text}}</text> -->
<FilmItem
v-for="item in films"
:key="item.filmId"
:item="item"
:is-on-show="true" />
<!-- 数据加载完毕时显示没有更多组件 -->
<NoMoreItem v-if="films.length >= total"></NoMoreItem>
<!-- 否则显示【Loadmore组件】 -->
<!-- API请参考:http://v1.uviewui.com/components/loadMore.html -->
<u-loadmore
v-else
bg-color="#eee"
style="height: 50px; line-height: 50px"
:status="status" />
</view>
</template>
<script>
/* 不符合easy-com规范的组件要引入+声明 */
import FilmItem from "../FilmItem.vue";
import NoMoreItem from "../NoMoreItem.vue";
export default {
/* 不符合easy-com规范的组件要引入+声明 */
components: {
FilmItem,
NoMoreItem,
},
// 没什么卵用,只是测试,好使!
expose: ["sayHello"],
props: {
// 要展示的电影数据
films: {
type: Array,
default() {
return [];
},
},
// 当前列表中的影片是否在映,在映就显示一个购票按钮,否则不显示
isOnShow: {
type: Boolean,
default: true,
},
// 当前列表的数据总量
total: {
type: Number,
default: 0,
},
// LoadMore组件的状态,默认可以加载更多
// API请参考:http://v1.uviewui.com/components/loadMore.html
status: {
type: String,
default: "loadmore",
},
},
methods: {
sayHello() {
console.log("hello from my-film-list");
},
},
};
</script>
<style>
.wrapper {
/* margin-bottom: 150px; */
height: 100%;
}
</style>
@主业务逻辑
- 代码全部来自 pages/film/film.vue
页面部署Tabs
<my-navbar
v-show="showNavbar"
:title="title">
</my-navbar>
<!-- Tabs吸顶时覆盖Navbar -->
<u-sticky z-index="100">
<!-- 这个元素用于撑开Tabs的高度,以完全覆盖Navbar -->
<view style="height: 50rpx; background-color: white"></view>
<!-- 具体属性含义请参考:http://v1.uviewui.com/components/tabs.html -->
<u-tabs
:height="100"
:bold="false"
:offset="[0, 0]"
bar-height="3"
bar-width="120"
active-color="#FF5F16"
:list="list"
:is-scroll="false"
:current="current"
@change="change"></u-tabs>
</u-sticky>
<view
class="page"
style="margin-top: 5rpx">
<!-- <playings v-if="current===0"></playings> -->
<!-- <comings v-else></comings> -->
<!-- 数据展示组件 -->
<my-film-list
ref="refMFL"
:films="list[current].films"
:total="list[current].total"
:status="list[current].status"
:isOnShow="list[current].isOnShow">
</my-film-list>
</view>
Tabs的配置
data() {
return {
title: "电影",
showNavbar: true,
/* tabs的相关配置 */
list: [
{
name: "正在热映",
type: 1, //服务端接口参数 1=正在热映 2=即将上映
isOnShow: true,
films: [], //当前tab子页面对应的数据
total: 1, //总数据量,至少会有一条数据
page: 0, //分页加载
status: "loadmore", //u-loadmore组件的状态
},
{
name: "即将上映",
type: 2,
isOnShow: false,
films: [],
total: 1,
page: 0,
status: "loadmore",
},
],
// 默认选中第0个tab
current: 0,
};
},
Tabs切换回调
methods: {
/* tabs切换时的回调 */
change(index) {
console.log("tab change", index);
this.current = index;
this.loadData(this.current);
},
...
}
加载数据方法
methods: {
/* tabs切换时的回调 */
change(index) {...},
/* 根据tabs序号加载数据 */
loadData(current) {
console.log("loadData:current=", current);
/* 如果u-loadmore组件正在加载 或者当前tab的所有数据均已加载完毕 就什么都不做 直接返回 */
if (
this.list[current].status === "loading" ||
this.list[current].films.length >= this.list[current].total
) {
console.log("this.list[current].films.length", this.list[current].films.length);
console.log("this.list[current].total", this.list[current].total);
console.log("loadData RETURNED!");
return;
}
/* 当前tab页码加加 u-loadmore组件标记正在加载 */
this.list[current].page++;
this.list[current].status = "loading";
/* 调用服务端接口获取数据 */
/*cityId=310100&pageNum=1&pageSize=10&type=1&k=9105116*/
uni.request({
url: "https://m.maizuo.com/gateway",
// GET参数
data: {
cityId: "310100",
pageNum: this.list[current].page, //页码
pageSize: 10,
type: this.list[current].type, //1=正在热映 2=即将上映
k: 9105116,
},
//自定义请求头信息
header: {
"X-Host": "mall.film-ticket.film.list",
},
// 加载数据成功
success: res => {
/* 留多点时间看每秒的loading动画 */
setTimeout(() => {
// console.log(res);
// this.text = 'request success';
/* 同步数据给当前tab */
this.list[current].films.push(...res.data.data.films);
this.list[current].total = res.data.data.total;
/* 数据全部加载完毕时 u-loadmore组件标记状态为加载完毕 否则标记为仍可继续加载 */
if (this.list[current].films.length >= this.list[current].total) {
this.list[current].status = "nomore";
} else {
this.list[current].status = "loadmore";
}
console.log("success", this.list);
}, 500);
},
// 失败回调
fail(err) {
console.log("fail:err=", err);
this.status = "nomore";
},
});
},
},
用户触发Tabs切换
methods: {
/* tabs切换时的回调 */
change(index) {
console.log("tab change", index);
this.current = index;
// 为当前tab加载数据
this.loadData(this.current);
},
...
}
用户上拉见底时加载下一页
/* 上拉见底时为当前tab加载下一页数据 */
/* onReachBottom为页面级组件独有的一个“生命周期” */
onReachBottom() {
console.log("onReachBottom");
this.loadData(this.current);
},
@源码地址
😈 点赞收藏加关注了吗??
本项目源码 watch,follow,fork!!!
祝大家撸码愉快~