阅读 238

uniapp实现多端的局部下拉刷新功能

其实在我的开发经历来讲,并不在意下拉刷新和触底加载的功能。直到有一天,一个朋友问题说,你的h5下拉刷新的功能是如何实现的。我的回答用插件啊。然而他给我的反馈是,市面上的插件都不是很好用。于是我就萌生了一个自己开发这个插件的念头。 二话不说,开始构思这个组件的功能,手起刀落就是干。 最早实现这个功能是使用vue3去实现的。 在npm 中搜索ive-vue-mobile可以找到插件包。下拉刷新功能只是ive-vue-mobile中的一个功能。想了解更多功能可以去ive-vue-mobile文档了解。 后来使用uniapp的时候发现要实现下拉刷新使用onRefresh只能实现整体的下拉刷新,使用scroll-view也要重新封装,不然的话代码会变得很复杂。于是开始重新封装这个组件去兼容各大平台。

好了。废话不多说,先说说这个组件的用法吧。到dcloud插件市场上搜索ive-pull-refresh就能搜索到啦。

image.png

众所周知,在uniapp中只要easycom模式在开发过程中就可以直接使用插件了。 所以先来看下拉刷新的例子:

<template>
<!-- 下拉刷新 -->
  <div>
    <ive-pull-refresh @refresh="refresh" class="scroll_wrapper" loosing-text="释放刷新">
      <div style="height: 100px; background: orange;">刷新次数{{times}}</div>
    </ive-pull-refresh>
  </div>
</template>

<script>
export default defineComponent({
  data() {
      return {
          times: 0
      }
  },
  methods: {
      refresh(end) {
          // 更新逻辑
        setTimeout(() => {
          this.times++;
          end();
        }, 2000);
      }
  }
});
</script>

<style lang="scss" scoped>
.scroll_wrapper{
  height: 100vh;
}
</style>
复制代码

这是一个下拉刷新的例子,设置好容器的高度,然后在组件中绑定一个refresh事件就可以轻松地实现下拉刷新的功能了。refresh携带了一个回调方法,调用该方法表示刷新成功,组件会从加载的状态变更为初始状态。

然而,我们下拉刷新经是和列表页一起使用的,所以下拉刷新也经常配合着触底加载一起使用。于是就有了下面的代码

<template>
  <!-- 下拉刷新&&触底加载 -->
  <div>
    <ive-pull-refresh
      :loadmoreable="true"
      @loadmore="loadmore"
      @refresh="refresh"
      class="scroll_wrapper"
    >
      <p style="padding: 10px" v-for="i in list" :key="i">ceshi{{ i }}</p>
    </ive-pull-refresh>
  </div>
</template>

<script>
export default{
    data() {
        return {
            list: [],
            page: 1,
            pageSize: 10
        }
    },
    methods: {
        getList(cb) {
            if (this.requestTimer) return; //模拟正在加载中
                // 模拟请求数据
            this.requestTimer = setTimeout(() => {
                // 模拟请求成功
                this.requestTimer && clearTimeout(this.requestTimer);
                this.requestTimer = 0;
                // 模拟接口返回的数据
                const moreData = [];
                const start = this.list[this.list.length - 1] || 0;
                // 随机生成返回数据的长度
                // const length = 0;
                const length = Math.random() > 0.4 ? 10 : Math.floor(Math.random() * 10);
                for (let i = 0; i < length; i++) {
                moreData.push(start + 1 + i);
                }
                // 将获取到的数据传递给回调函数
                cb && cb(moreData);
            }, 1000);
        },
        refresh(next) {
        // 初始化数据
            this.list = [];
            this.page = 1;
            next();
        },
        loadmore(next){
        // 获取列表
        this.getList((data) => {
            this.page++;
            this.list = [...this.list, ...data];
            // 当返回的数据内容小于pageSize的时候说明没有更多了
            if (data.length < this.pageSize) {
                // 传入true表示没有更多了,不再触发触底加载
                next(true);
                } else {
                // 不传参数状态变为:上拉显示更多状态, 为下一次触底加载做准备
                next();
            }
            });
        }
    },
}
</script>

<style lang="scss" scoped>
.scroll_wrapper {
  height: 500px;
  margin-top: 40px;
  background: #f5f5f5;
}
</style>

复制代码

组件第一次加载的时候会自动调用loadmore方法,loadmore里面的内容是你自己的加载列表的业务逻辑。通过loadmore方法携带的回调函数next去告知页面是否继续加载。next(true)像这样传入一个true的值则表示列表没有更多了,再次滚动到底部则不会触发loadmore方法。如果next()不传或者传入false则表示还有,下次触底会继续调用loadmore方法,直到调用next(true);

image.png

这是以上代码实现出来的效果

在使用这个组件的时候不需要自己去考虑一页列表的内容是否能填满容器(或者整页)而不能触发loadmore方法,组件初始化的时候会自动调用loadmore方法的时候会自己填充页面内容(只要你设置好容器的高度即可),如果页面填充满了或者没有更多了(也就是你的业务逻辑中调用了next(true))或者,组件会自动停止填充。

注意:
1、组件必须设置高度,可以使用flex布局。
2、如果一个页面使用多个ive-pull-refresh组件,可以使用v-if来控制组件的更新,或者使用组件的refresh方法:this.$refs.pullRefresh.refresh();
3、使用触底加载的时候loadmoreable需要设置为true
4、在触底加载功能开启的时候,如果容器中没有内容,会自动出现empty图片,如果需要设置,可以根据文档修改

查看更详细的内容

创作不易,如果你觉得好用,打赏一个呗~

image.png

image.png

文章分类
前端
文章标签