实现首页滚动加载 | 青训营笔记

103 阅读1分钟

这是我参与「第四届青训营 」笔记创作活动的第12天。

前言

在仿掘金的项目中,首页就是一个无限滚动的技术文章列表,那如何实现这个效果呢? 不可能说直接把所有的文章直接渲染到页面上,因为会造成不必要的资源消耗。 下面是简单的实现原理。

首页无限滚动

主要完成两件事:

  • 监听滚动
  • 发现快滚到底了,就再来点新的

如何判断快滚到底了?

我们首先来看一张图片:

image.png

页面里有几个数值可以用

  • 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…

有时间的话可以研究一下。