vant中list的使用以及首次加载触发两次解决问题
作者:山竹回家了
这篇文章主要介绍了vant中list的使用以及首次加载触发两次解决问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
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,表示加载结束
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。