移动端滚动加载更多组件 - loadermore

本贴最后更新于 1598 天前,其中的信息可能已经物是人非

移动端滚动加载更多组件

前言

之前在移动端需求的时候,有个功能点就是关于滚动加载,滚动到底部以后,自动执行下次请求。本来想着使用公司内部基础组件的,但是发现基础组件没有(内部一般禁止引入一些大公司的组件,风险问题)。

看了其他开源的单组件,写的都挺好的,但是整体代码量较多,内心是存在排斥心理的,所以...

没办法,只能手撸了~

实现

配置
配置 默认值 备注
pageIndex 1 分页请求 index
pageSize 10 分页请求 size
totalCount 0 分页请求 count
delay 500(ms) 延迟请求
bottom 25 滚动条到达底部多少就会自动请求数据
fail False 请求失败需要让组件知道,为 true,则更改提示
failTips '请求失败,稍候重试!' 请求失败需要展示的信息
原理

监听滚动,当滚动到用户配置的 bottom 时,执行下次请求,当请求完毕,不执行请求。当请求失败时,提示组件请求失败,增加提示失败信息。

代码
<template>  <div    id="loadMore"    class="loadmore"  >    <slot></slot>    <div      class="loadmore-tip"      id="loadTips"      v-if="totalCount > 0 && totalCount >= pageSize"    >      <i        v-show="loadTips=='正在加载中'"        class="loadmore-icon"      ></i>      {{loadTips}}    </div>  </div> </template> <script> let timer = null // 不作为响应式变量,提升性能 export default {    props: {        pageIndex: {            type: Number,            default: 1       },        pageSize: {            type: Number,            default: 10       },        totalCount: {            type: Number,            default: 0       },        delay: {            type: [Number],            default: 500       },        // 滚动条到达底部多少就会自动请求数据        bottom: {            type: [Number],            default: 25       },        // 请求失败预防针,测试中发现的这个        fail: {            type: Boolean,            default: false       },        failTips: {            type: String,            default: '请求失败,稍候重试!'       }   },    data () {        return {            loadTips: '正在加载中'       };   },    watch: {        pageIndex () {            this.loadMore()       },        totalCount: {            handler (val, oldval) {                if (val > 0) {                    this.loadMore()               }           },            // 首次请求            immediate: true       },        fail (value) {            if (value) {                this.loadTips = this.failTips           }       }   },    methods: {        // 上滑动加载更多        loadMore () {            this.loadTips = '正在加载中';            const {pageSize, pageIndex, totalCount} = this            return new Promise((resolve, reject) => {                window.onscroll = () => {                    timer = setTimeout(() => {                        if (!document.getElementById('loadTips')) return                        const clientHeight = document.documentElement.clientHeight || document.body.clientHeight || 0                        const rectBottom = document.getElementById('loadTips').getBoundingClientRect().bottom || 0                        if (rectBottom < clientHeight + this.bottom) {                            const size = totalCount - pageIndex * pageSize                            if (size > 0) {                                this.$emit('loadmore', pageIndex + 1)                                resolve(true)                           } else {                                this.loadTips = '没有更多数据了'                                resolve(false)                           }                            clearTimeout(timer)                       }                   }, this.delay)               }           })       }   },    beforeDestroy () {        clearTimeout(timer)   } }; </script> <style lang="scss" scoped> .loadmore-tip {  color: #aaa;  font-size: 12px;  text-align: center;  height: 40px;  line-height: 40px; } @keyframes rotate-loading {  0% {    -webkit-transform: rotate(0);    transform: rotate(0); }  100% {    -webkit-transform: rotate(360deg);    transform: rotate(360deg); } } @-webkit-keyframes rotate-loading {  0% {    -webkit-transform: rotate(0);    transform: rotate(0); }  100% {    -webkit-transform: rotate(360deg);    transform: rotate(360deg); } } .loadmore-icon {  vertical-align: -2px;  width: 12px;  height: 12px;  display: inline-block;  background: url("data:image/png;base64,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")    no-repeat;  background-size: 12px 12px;  -webkit-animation: rotate-loading 0.5s linear forwards infinite;  animation: rotate-loading 0.5s linear forwards infinite; } </style>
  • 分享

    有什么新发现就分享给大家吧!

    248 引用 • 1794 回帖 • 2 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖
  • 代码
    467 引用 • 586 回帖 • 9 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...