这是我参与「第四届青训营 」笔记创作活动的第12天。
前言
在仿掘金的项目中,首页就是一个无限滚动的技术文章列表,那如何实现这个效果呢? 不可能说直接把所有的文章直接渲染到页面上,因为会造成不必要的资源消耗。 下面是简单的实现原理。
首页无限滚动
主要完成两件事:
- 监听滚动
- 发现快滚到底了,就再来点新的
如何判断快滚到底了?
我们首先来看一张图片:
页面里有几个数值可以用
- 1-
scrollTop:滚动距离 - 2-
scrollHeight:页面内容总高度 - 3-
clientHeight:可视区高度
事先定义一个触发距离,比如 300px 。
那我们触发的条件是:当实际计算的距离要小于或者等于预先定义好的距离时。
此时可以触发新的一次加载了。
// 当实际计算的距离要小于或者等于预先定义好的距离时
const distance = 300px
shouldTrigger = scrollHeight - (clientHeight + scrollTop) <= distance
防止重复加载
加一把“锁”,把他"锁住",在加载完成前,不允许其再次触发
let readyForLoad = true; //默认允许加载一次
if (readyForLoad) {
//需要加载才进来,防止重复
readyForLoad = false; //进来了就"锁上"
axios("/datas.json").then((res) => {
datas.value = [...datas.value, ...res.data];
readyForLoad = true; //加载完了才"开锁",允许再次触发
});
}
使用 element plus 实现
也可以使用 element plus 实现.
发送axios向后端请求数据
import request from "./request";
export function GetPostList() {
return request({
url: `http://localhost:8080/v1/postlist`,
});
}
export function GetPostListWithTime(data: any) {
return request({
url: `http://localhost:8080/v1/postlist?latest_time=${data.nextTime}`,
});
}
前端
部分核心代码
<template>
......
<ul
infinite-scroll-immediate="false"
v-infinite-scroll="load"
class="list-wrap"
style="overflow: auto"
>
<li class="item" v-for="item in articleList" :key="item.post_id">
<div class="info-bar">
{{ item.author_name }}
<div class="divider"></div>
{{ item.created_at }}
<div class="divider"></div>
{{ item.community_name }}
</div>
<div class="info-main">
<div class="main-title">{{ item.title }}</div>
<div class="main-context">{{ item.content }}</div>
</div>
</li>
</ul>
......
</template>
<script lang="ts" setup>
......
import { GetPostList, GetPostListWithTime } from "@/utils/api/article";
import { ref, onBeforeMount } from "vue";
import { ElMessage } from "element-plus";
const articleList = ref();
const nextTime = ref();
// 监听页面滚动到底,是时候加载数据了
function load() {
GetPostListWithTime({ nextTime: nextTime.value }).then((res: any) => {
console.log(res);
if (res.code != 1000) {
ElMessage({
message: res.message,
type: "error",
});
return;
}
// message: `获取列表成功!`
articleList.value = [...articleList.value, ...res.data];
nextTime.value = res.data.next_time;
});
}
onBeforeMount(() => {
GetPostList().then((res: any) => {
console.log(res);
if (res.code != 1000) {
ElMessage({
message: res.message,
type: "error",
});
return;
}
// message: `获取列表成功!`
articleList.value = res.data;
nextTime.value = res.next_time;
console.log("onBeforeMount", nextTime.value);
});
});
</script>
<style scoped lang="less">
......
</style>
总结
然后实际打代码的时候发现element plus 有相似的无限滚动,他是开源的,可以学习一下,地址:element-plus.org/zh-CN/compo…
有时间的话可以研究一下。