在vuejs中如何实现滑动滚动条来动态加载数据

#金石计划征文活动

前言

vuejs中,我们经常使用axios来请求数据,但是有时候,我们请求的数据量很大,那么我们如何实现滑动滚动条来加载数据呢?

实现思路

  1. 首先,我们需要在vuejs中引入axios
  2. 然后,我们需要从vue中,引入onMounted,onUnmounted生命周期钩子函数 然后,我们需要在onMounted函数中,进行监听 而在onUnmounted函数中,我们需要取消监听,解绑
  3. 编写事件处理函数handleScroll, 获取变量scrollTop是滚动条滚动时,距离顶部的距离,获取变量scrollHeight是滚动条的总高度,获取变量clientHeight是滚动条可视区域的高度
  4. 当滚动条到达底部,并且距离底部小于10px时,加载数据,也就是请求axios数据,页码++,重新加载数据函数
  5. 为了防止用户频繁触发下拉滑动滚动条,往往需要添加一个函数防抖,在指定的时间内,只执行最后一次事件处理函数,避免频繁请求数据,给服务器造成压力

代码实现

xml 复制代码
<template>
    <div>
          <div>
            <el-button type="primary"  @click="handleBtnGetJoke">请求数据</el-button>
            <el-button type="danger" @click="handleBtnClearData" v-if="aDatas.length > 0?true:false">清空数据</el-button>
          </div>  
          <div>
            <ul v-if="aDatas.length > 0?true:false">
                <li class="joke-list" v-for="item in aDatas"
                                    :key="item.hashId">{{ item.content }}
                </li>
                <div class="loading" v-if="aDatas.length > 0?true:false"> 
                    <el-button size="mini"  type="primary" @click="handleBtnLoading" >加载</el-button>
                </div>
            </ul> 
          </div>
    </div>
</template>

<script setup>
import axios from "axios";
import { ref,onMounted,onUnmounted  } from "vue";

let aDatas = ref([]);
let page = ref(1);
let pagesize = ref(20);

onMounted(() => {
    // 获取数据
    handleBtnGetJoke();
    window.addEventListener('scroll', debounce(handleScroll,500));
})

onUnmounted(() => {
    window.removeEventListener('scroll', handleScroll);
})

// 事件处理函数
function handleScroll() {
    // 变量scrollTop是滚动条滚动时,距离顶部的距离
    const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    // 变量scrollHeight是滚动条的总高度
    const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
     // 变量clientHeight是滚动条可视区域的高度
    const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
     // 当滚动条到达底部,并且距离底部小于10px时,加载数据   
    if (scrollTop + clientHeight - scrollHeight <= 10) {
        page.value++;
        handleBtnGetJoke();
    }
}

// 函数的防抖
function  debounce(method, duration) {
         var timer = null;
         return function(){
            var that = this,
                args = arguments;
            // 在本次调用之间的一个间隔时间内若有方法在执行,则终止该方法的执行
            if(timer) {
              clearTimeout(timer);
            }
            // 开始执行本次调用
            timer = setTimeout(function(){
              method.apply(that,args);
            }, duration)
          }

  }


async function handleBtnGetJoke() {
    const params = {
        key: 'aa1b7ad08be2a09a4e0d2d46897e2dc8',
        page: page.value,
        pagesize:pagesize.value,
        time: 1418816972
    }

    const response =  await axios.get('/api/joke/content/text.php',{params})
    console.log(response);
    if(response.status == 200) {
        const { data } = response.data.result;
        console.log(data);
        aDatas.value = aDatas.value.concat(data);
        if(page.value*pagesize.value >= data.length) {
            alert("没有更多数据了")
        }

    }
}

// 加载数据,叠加
function handleBtnLoading() {
    page.value++;
    handleBtnGetJoke(); 
}

// 清空数据
function handleBtnClearData() {
    aDatas.value = [];
}


</script>

<style scoped>
.joke-list {
    list-style-type: decimal;
    list-style-position: outside;
    padding: 5px 0;
    border-bottom: dashed 1px #ccc;
}

.loading {
    margin: 0 auto;
    text-align:center;
}
</style>

其中核心防抖函数如下所示,实现方式也很简单,就是利用定时器,在规定的时间内,如果再次触发,则清除定时器,重新开始计时。

只执行最后一次

javascript 复制代码
// 函数的防抖
function  debounce(method, duration) {
         var timer = null;
         return function(){
            var that = this,
                args = arguments;
            // 在本次调用之间的一个间隔时间内若有方法在执行,则终止该方法的执行
            if(timer) {
              clearTimeout(timer);
            }
            // 开始执行本次调用
            timer = setTimeout(function(){
              method.apply(that,args);
            }, duration)
          }

  }

至于怎么样判断数据是否加载完毕,到最后一页

每次在请求完成数据的时候去判断一下当前的 page × pagesize是否已经大于等于接口返回的total值就行了,也可以是pageNum 等于total 的时候,就说明已经没有数据了,可以提示用户了

scss 复制代码
if(page.value*pagesize.value >= data.length) {
            alert("没有更多数据了")
}

总结

其实这个功能很简单,但是写起来还是有点麻烦,因为涉及到异步请求,所以需要判断数据是否加载完毕,还要判断是否最后一页,还要判断是否还有数据,还要判断是否需要提示用户没有更多数据了,所以代码量还是挺多的,但是写完之后,感觉还是挺有成就感的。

什么上拉,下拉刷新,下拉加载更多,其实原理都差不多,都是利用了防抖函数,然后利用定时器,在规定的时间内,如果再次触发,则清除定时器,重新开始计时。 实现方式都差不多

相关推荐
光影少年7 天前
react打包优化和配置优化都有哪些?
前端·react.js·掘金·金石计划
光影少年9 天前
Promise.all实现其中有一个接口失败其他结果正常返回,如何实现?
前端·promise·掘金·金石计划
光影少年10 天前
react16中的hooks的底层实现原理
前端·react.js·掘金·金石计划
光影少年19 天前
vite打包优化有哪些
前端·vite·掘金·金石计划
光影少年21 天前
webpack打包优化
webpack·掘金·金石计划·前端工程化
光影少年22 天前
Typescript工具类型
前端·typescript·掘金·金石计划
光影少年1 个月前
Promise状态和方法都有哪些,以及实现原理
javascript·promise·掘金·金石计划
光影少年1 个月前
next.js和nuxt与普通csr区别
nuxt.js·掘金·金石计划·next.js
光影少年1 个月前
js异步解决方案以及实现原理
前端·javascript·掘金·金石计划
光影少年1 个月前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划