uniapp实现上拉加载和下拉刷新

5,136 阅读1分钟

uniapp实现上拉加载和下拉刷新

当我们在做移动端开发时,经常会遇到需要上拉加载更多或下拉刷新数据的需求。而如果使用原生开发,对于不同的平台,需要编写不同的代码,工作量大且繁琐。这时候,我们可以使用uniapp来实现一次性编写代码,同时支持多个平台。本文将详细介绍如何在uniapp中实现上拉加载和下拉刷新功能。

一、什么是上拉加载和下拉刷新

上拉加载:当列表滚动到底部时,继续向下滑动,此时页面会自动加载更多的数据。

下拉刷新:当列表顶部被下拉时,松手时会触发刷新操作,重新加载最新的数据。

二、使用uniapp实现上拉加载和下拉刷新
  1. 在uniapp中使用第三方组件库“uView”,在组件库中已经封装好了上拉加载和下拉刷新的组件,我们只需要引入即可。
<template>
  <view>
    <u-list-view
      :refresh="true"
      :loadmore="true"
      :list="listData"
      :load-text="loadText"
      :no-more-text="noMoreText"
      :ref="listView">
      <view slot="list" v-for="(item,index) in listData" :key="index">
        <!-- 列表项 -->
        <view>{{item.title}}</view>
      </view>
    </u-list-view>
  </view>
</template>

<script>
import uListView from '@/components/u-list-view/u-list-view.vue'

export default {
  components: {
    uListView
  },
  data() {
    return {
      listData: [],
      loadText: '上拉加载更多',
      noMoreText: '已经到底了',
      page: 1,
      pageSize: 10
    }
  },
  methods: {
    // 下拉刷新事件
    onRefresh() {
      // 模拟请求数据
      setTimeout(() => {
        this.listData = [
          {title: '刷新数据1'},
          {title: '刷新数据2'},
          {title: '刷新数据3'}
        ]
        uni.stopPullDownRefresh()
      }, 1500)
    },

    // 上拉加载更多事件
    onLoadMore() {
      // 模拟请求数据
      setTimeout(() => {
        const newData = []
        for (let i = 0; i < this.pageSize; i++) {
          newData.push({
            title: `第${(this.page - 1) * this.pageSize + i + 1}项`
          })
        }

        this.listData = [...this.listData, ...newData]

        uni.hideLoading()
        if (this.listData.length >= 30) {
          this.loadText = ''
          uni.showToast({
            icon: 'none',
            title: this.noMoreText
          })
        } else {
          this.page++
        }
      }, 1500)
    }
  }
}
</script>
  1. 在uniapp中不使用第三方组件库,而是自己实现上拉加载和下拉刷新
<template>
  <view>
    <!-- 下拉刷新区域 -->
    <view class="refresh"
      :style="{top: '-'+rHeight+'px'}"
      ref="refresh"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd">
      <view :style="{height: rHeight+'px'}">
        <view v-if="rState === 0">下拉刷新</view>
        <view v-else-if="rState === 1">松手开始刷新</view>
        <view v-else>正在刷新中</view>
      </view>
    </view>

    <!-- 列表 -->
    <view class="list"
      ref="list"
      :style="{top: rHeight+'px'}"
      :scroll-y="true"
      :scroll-top="scrollTop"
      :scroll-with-animation="true"
      @scrolltolower="onLoadMore">
      <view v-for="(item,index) in listData" :key="index">
        <!-- 列表项 -->
        <view>{{item.title}}</view>
      </view>
    </view>

    <!-- 上拉加载更多提示 -->
    <view class="load-more"
      v-if="!isLoaded && !isAllLoaded">
      {{loadText}}
    </view>
    <view class="no-more"
      v-if="isAllLoaded">
      {{noMoreText}}
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      listData: [],
      loadText: '上拉加载更多',
      noMoreText: '已经到底了',
      isLoaded: false,
      isAllLoaded: false,
      scrollTop: 0,
      startY: 0,
      rHeight: 0,
      rState: 0 // 0: 下拉刷新,1: 松手开始刷新,2: 正在刷新中
    }
  },
  methods: {
    // 下拉刷新触摸事件
    onTouchStart(e) {
      this.startY = e.touches[0].clientY
      this.rHeight = 0
    },
    onTouchMove(e) {
      if (this.isLoaded) return

      const distance = e.touches[0].clientY - this.startY
      if (distance < 0 || this.scrollTop > 0) return

      e.preventDefault()

      this.rHeight = Math.min(-this.scrollTop, Math.abs(distance))

      if (this.rHeight >= 80) {
        this.rState = 1
      } else {
        this.rState = 0
      }
    },
    onTouchEnd() {
      if (this.isLoaded) return

      if (this.rState === 1) {
        this.rHeight = 40
        this.rState = 2
        this.onRefresh()
      } else {
        this.rHeight = 0
        this.rState = 0
      }
    },

    // 下拉刷新事件
    onRefresh() {
      // 模拟请求数据
      setTimeout(() => {
        this.listData = [
          {title: '刷新数据1'},
          {title: '刷新数据2'},
          {title: '刷新数据3'}
        ]

        this.scrollTop = 0
        this.rHeight = 0
        this.rState = 0

        uni.stopPullDownRefresh()
      }, 1500)
    },

    // 上拉加载更多事件
    onLoadMore() {
      if (this.isLoaded || this.isAllLoaded) return

      const windowHeight = uni.getSystemInfoSync().windowHeight
      const listHeight = this.$refs.list.$el.offsetHeight
      if (windowHeight - listHeight < 130) return

      this.isLoaded = true
      this.loadText = '正在加载中...'

      // 模拟请求数据
      setTimeout(() => {
        const newData = []
        for (let i = 0; i < 10; i++) {
          newData.push({
            title: `第${this.listData.length + i + 1}项`
          })
        }

        if (newData.length === 0) {
          this.isAllLoaded = true
          this.loadText = ''
          this.noMoreText = '已经到底了'
        } else {
          this.isLoaded = false
          this.listData = [...this.listData, ...newData]
        }
      }, 1500)
    }
  }
}
</script>
三、小结

上拉加载和下拉刷新是移动端开发中常用的功能,使用uniapp可以避免对于不同平台的单独编写代码的麻烦。本文介绍了在uniapp中如何实现上拉加载和下拉刷新,如果你需要实现这些功能,可以选择引入第三方组件库或者自己实现。希望本文能够帮助你快速实现这些功能,提升你的开发效率!