vant中list使用及首次加载触发两次
以下是list的基本使用方法,主要原理就是当页面数据小于offset这个高度的时候,就会触发load,在load里面需要调用接口发送下一页的数据.所以发送完毕后需要将设置分页的属性加一,并将获取到的新值push进接收数据的数组里,而不是直接赋值,如果直接赋值那么数组里就只有新值,之前的值就被覆盖.
调用完以后将loading的样式关闭,并且判断数据库中还有没有数据,如果没有,就将finished为true,表示已经加载完毕了.
首次加载触发两次解决问题
1.在mounted或者create调用,原因是有可能在数据没回来的时候load就监测到数据低于高度,也发送了一次,等到数据回来时已经请求两次了.所以干脆不需要调用,交给load检测即可.
2.offset过于高,默认的高度是300,有一次获取数据一次只获取5条,虽然覆盖了页面高度,但稍作触碰就会二次发送.
3.请求的数据过少,请求的数据不足以覆盖页面就会二次加载,可以看文档list第一条示例便是.
<template>
<div>
<div class="groupBuyingList">
<!-- 加入加载 -->
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
:offset='50'
>
<!-- 每个模块 -->
<div class="activity" v-for="(item, index) in results" :key="index">
<img :src="item.photo" alt="" />
<div class="title">{{ item.cname }}</div>
<div class="groupPeople">
<span>{{ item.groupLabel }}</span>
</div>
<div class="operation">
<div class="money">
<!-- 拼团价 -->
<div class="groupMoney">
<span>¥</span>{{ item.groupPrice }} <span>起</span>
</div>
<!-- 原价 -->
<div class="originalCost">¥{{ item.underlinedPrice }}</div>
</div>
<div class="share" @click="handleGo(item)">
<span> 去开团 </span>
</div>
</div>
</div>
</van-list>
</div>
</div>
</template>
<script>
import { activityList } from "../../../api/appletGroupBuying/groupBuyingActivity";
export default {
data() {
return {
userInfo: {
// 条数
pageNum: 1,
},
loading: false, //加载中状态
finished: false, //是否加载
// 接收列表数据
results: [],
// 总条数
rowCount: "",
};
},
mounted() {
},
methods: {
async activityList() {
let res = await activityList(this.userInfo);//发送请求
// console.log(this.results);
// 如果没有数据
if (res.data.ret.results === null) {
this.results = [];
this.finished = true; // 停止加载
} else {
// 总条数
this.rowCount = res.data.ret.rowCount;
// 将数据放入数组
this.results.push(...res.data.ret.results);
this.loading = false; // 加载状态结束
// 如果list长度大于等于总数据条数,数据全部加载完成
//this.finished = true 结束加载状态
this.results.length >= this.rowCount ? (this.finished = true) : "";
}
},
onLoad() {
this.activityList(this.userInfo); // 调用上面方法,请求数据
this.userInfo.pageNum++; // 分页数加一
},
},
};
</script>
<style lang="less" scoped>
.groupBuyingList {
padding: 20px;
background: #f4f4f4;
//每个活动
.activity {
padding: 30px 35px;
margin-bottom: 32px;
width: 710px;
background: #ffffff;
border-radius: 20px;
box-sizing: border-box;
> img {
width: 100%;
}
//
.title {
margin-top: 30px;
width: 100%;
height: 40px;
font-size: 28px;
font-weight: bold;
line-height: 40px;
color: #545353;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 拼团人数
.groupPeople {
margin-top: 26px;
margin-bottom: 14px;
display: flex;
align-items: center;
span {
padding: 0 3px 0 3px;
border: 2px solid #ff7f00;
border-radius: 10px;
font-size: 24px;
font-weight: 400;
line-height: 33px;
color: #ff7f00;
}
}
.operation {
display: flex;
justify-content: space-between;
.money {
display: flex;
// 拼团价
.groupMoney {
display: flex;
margin-right: 13px;
height: 62px;
font-size: 44px;
font-weight: bold;
line-height: 62px;
color: #ff8105;
span {
font-size: 30px;
}
}
// 原价
.originalCost {
text-decoration: line-through;
width: 119px;
height: 40px;
font-size: 28px;
line-height: 60px;
color: #b5b4b1;
}
} //分享获客
.share {
width: 180px;
height: 60px;
background: #ff8105;
display: flex;
align-items: center;
border-radius: 20px;
span {
width: 100%;
line-height: 60px;
text-align: center;
font-size: 29px;
font-weight: bold;
line-height: 37px;
color: #ffffff;
}
}
}
}
}
</style>
vant中list列表组件使用
List 的运行机制:
List 会监听浏览器的滚动事件并计算列表的位置,当列表底部与可视区域的距离小于offset时,List 会触发一次 load 事件。
1. 基础结构
<van-list
v-model="loading" // 是否显示正在加载状态
:finished="finished" // 是否已经加载完成
finished-text="没有更多了" // 加载完成提示文案
@load="onLoad" // 滚动条与底部距离offset时触发事件
offset="300" // 滚动条与底部距离offset时触发@load(默认300)
:error.sync="error" // 是否显示加载失败状态
error-text="请求失败,点击重新加载" // 加载失败提示文案
>
<van-cell v-for='(item, index) in list' :key="index"> // 循环列表数据
<div>{{item}}循环出来的数据<div>
</van-cell>
</van-list>
2.data声明:
data() {
return {
loading: false, // 是否处在加载状态
finished: false, // 是否已加载完成
error: false, // 是否加载失败
list: [], // 数据项
page: 1, // 分页
page_size: 10 // 每页条数
total: 0 // 数据总条数
}
}
3.methods定义方法
methods: {
onLoad() {
// 异步更新数据
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
setTimeout(() => {
for (let i = 0; i < 10; i++) {
this.list.push(this.list.length + 1);
}
// 加载状态结束
this.loading = false;
// 数据全部加载完成
if (this.list.length >= 40) {
this.finished = true;
}
}, 1000);
},
},
};
4.调用api渲染页面
导入这个接口 import { } from '@/api/xxx.js'
async onLoad () {
const res = await 接口方法名(this.channel.id, Date.now())
// 获取的数据
const arr = res.data.data.results // 它是一个数组
// 1. 追加数据到list
// 对数组进行展开
this.list.push(...arr)
// 2. 把loading设置为false
this.loading = false
// 3. 判断是否所有的数据全部加载完成,如果是:finished设为true
if (arr.length === 0) {
// 说明取不到数据了
this.finished = true
}
// 4. 页面上提示一下用户
this.$toast.success('成功加载数据')
}
loading 和 finished 分别是什么含义?
List有以下三种状态,理解这些状态有助于你正确地使用List组件:
- 非加载中,loading为false,此时会根据列表滚动位置判断是否触发load事件(列表内容不足一屏幕时,会直接触发)
- 加载中,loading为true,表示正在发送异步请求,此时不会触发load事件
- 加载完成,finished为true,此时不会触发load事件
在每次请求完毕后,需要手动将loading设置为false,表示加载结束
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。