简单实现一个上拉加载更多分页组件

221 阅读4分钟

说在前面

🎈上拉加载更多的分页功能大家应该都见过或者使用过了吧?那么有多少同学自己实现过吗?今天我们来简单实现一个上拉加载更多分页组件。

效果展示

体验地址

jyeontu.xyz/jvuewheel/#…

实现思路

1、组件模板结构

<template>
    <div class="j-page-content" ref="scrollable" @scroll="handleScroll">
        <slot></slot>
        <div v-if="loading" class="loading-indicator">{{ moreText }}</div>
    </div>
</template>
  • 可滚动容器:最外层是一个内容容器,并且设置了 @scroll 事件监听器,当用户滚动这个容器时,会触发 handleScroll 方法。
  • 内容插槽<slot> 元素用于接收外部传入的内容。这意味着使用者可以在使用该组件时,将需要展示的列表项或者其他内容放置在这个组件内部,灵活性很高。
  • 加载提示:当 loadingtrue 时,会显示一个带有加载文本的 div。加载文本通过 moreText 属性传入,默认值为 "加载中..."。这个加载提示元素位于容器底部。

2、组件属性(props)

props: {
    moreText: {
        type: String,
        default: "加载中...",
    },
    threshold: {
        type: String,
        default: "20",
    },
}
  • moreText:用于定义加载提示文本的内容。外部使用者可以根据自己的应用场景和语言需求,自定义这个文本。
  • threshold:用于设置判断接近容器底部的阈值。默认值为 "20",它表示当距离容器底部的距离小于等于这个阈值时,触发加载更多的操作。这个值可以根据实际的设计需求和视觉效果进行调整。

3、组件数据(data)

data() {
    return {
        loading: false,
        isNearBottom: false,
        scrollableElement: null,
        isloading: false,
    };
}
  • loading:用于表示当前是否正在加载更多数据。初始值为 false,当触发加载更多操作时,设置为 true,加载完成后再重置为 false
  • isNearBottom:用于判断是否接近容器底部。通过在滚动事件处理中计算得到,初始值为 false
  • scrollableElement:用于存储可滚动容器的引用。在组件挂载(mounted)阶段获取到对带有 ref="scrollable"div 的引用。
  • isloading:这是一个额外的加载状态标识,用于在加载过程中防止多次触发加载更多操作。初始值为 false,在触发加载更多操作时设置为 true,并在加载完成后的短暂延迟后重置为 false

4、组件生命周期(mounted)

mounted() {
    this.scrollableElement = this.$refs.scrollable;
}

这里通过 this.$refs.scrollable 获取到在模板中定义的可滚动容器的引用,并将其赋值给 scrollableElement,以便在后续的滚动事件处理中使用。

5、组件方法(methods)

(1) handleScroll 方法

handleScroll() {
    if (this.isloading) return;
    const scrollTop = this.scrollableElement.scrollTop;
    const clientHeight = this.scrollableElement.clientHeight;
    const scrollHeight = this.scrollableElement.scrollHeight;

    // 判断是否接近底部
    this.isNearBottom =
        scrollTop + clientHeight >= scrollHeight - this.threshold;

    if (this.isNearBottom &&!this.loading) {
        this.loading = true;
        this.isloading = true;
        this.$emit("loadMore");
    }
}
  • 首先,该方法会检查 isloading 的状态,如果正在加载(isloadingtrue),则直接返回,避免多次触发加载操作。
  • 然后,获取可滚动容器的当前滚动位置(scrollTop)、可视区域高度(clientHeight)以及整个可滚动内容的高度(scrollHeight)。通过计算判断是否接近底部(scrollTop + clientHeight >= scrollHeight - this.threshold)。
  • 如果接近底部且当前没有在加载(!this.loading),则将 loadingisloading 都设置为 true,并通过 this.$emit("loadMore") 向外抛出一个名为 loadMore 的自定义事件。父组件可以监听这个事件来执行加载更多数据的操作。

(2)loadMoreComplete 方法

loadMoreComplete() {
    this.loading = false;
    setTimeout(() => {
        this.isloading = false;
    }, 100);
}

当父组件完成加载更多数据的操作后,应该调用这个方法。它首先将 loading 设置为 false,表示加载操作已完成。然后,通过 setTimeout 设置一个 100 毫秒的延迟后,将 isloading 也设置为 false。这样的延迟是为了确保在加载完成后的短暂时间内不会再次触发加载更多操作,避免可能出现的问题。

组件使用

<template>
    <div class="content" style="height: 500px">
        <JPageContent @loadMore="loadMoreData" ref="JPageContent">
            <div v-for="n in nums" :key="n">
                <div
                    style="
                        height: 100px;
                        width: 400px;
                        text-align: center;
                        line-height: 100px;
                        border: 1px solid gray;
                    "
                >
                    JPageContent-{{ n }}
                </div>
            </div>
        </JPageContent>
    </div>
</template>
<script>
export default {
    data() {
        return {
            nums: 10,
        }
    },
    methods: {
        loadMoreData() {
            if (this.nums >= 30) {
                this.$refs.JPageContent.loadMoreComplete();
                return;
            }
            setTimeout(() => {
                this.nums += 10;
                this.$refs.JPageContent.loadMoreComplete();
            }, 1000);
        }
    }
}
</script>

组件库

组件文档

目前该组件也已经收录到我的组件库,组件文档地址如下: jyeontu.xyz/jvuewheel/#…

组件内容

组件库中还有许多好玩有趣的组件,如:

  • 评论组件
  • 词云
  • 瀑布流照片容器
  • 视频动态封面
  • 3D轮播图
  • web桌宠
  • 贡献度面板
  • 拖拽上传
  • 自动补全输入框
  • 图片滑块验证

等等……

组件库源码

组件库已开源到gitee,有兴趣的也可以到这里看看:gitee.com/zheng_yongt…

🌟觉得有帮助的可以点个star~

🖊有什么问题或错误可以指出,欢迎pr~

📬有什么想要实现的组件或想法可以联系我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

公众号发送『组件库』即可获取源码链接。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。