使用 Vant van-pull-refresh van-list van-tab van-search遇到的问题总结

使用 Vant van-pull-refresh van-list van-tab van-search遇到的问题总结

  • 通过mixin封装van-pull-refresh + van-list , 实现下拉刷新 + 上拉加载,兼容切换tab changeTab + 搜索search

    // mixin
    
    // 下拉刷新 + 上拉加载
    export default {
      data () {
        return {
          list: [],
          page: 1,
          pageSize: 10,
          total: 0,
          // 下拉刷新
          refreshing: false,
          // 上拉加载
          loading: false,
          // 加载完毕
          finished: false,
          // 其他操作状态需要保持页码不变
          isKeepPage: false
        }
      },
    
      mounted () {
      	// 针对部分页面不需要在mounted阶段就初始化list, 判断如果在当前页面的options中有这个值且为真,则默认不加载list数据
        // this.$options => https://www.cnblogs.com/luguankun/p/10856911.html
        let doNotInit = this.$options.doNotInit
        if (!doNotInit) {
          this.onLoad()
        }
      },
    
      methods: {
        // 上拉加载
        onLoad () {
          // 获取数据条件: finished 为假, 或total 为0, 或当前页面数据长度小于总数据长度
          if (!this.finished || this.total === 0 || this.list.length < this.total) {
            // 显示加载的loading
            this.$toast.loading({
              message: '加载中...',
              forbidClick: true
            })
            // 调用引用的组件中的getList方法获取数据, 走对应的后台接口获取数据
            return this.getList().then(res => {
              const resData = res.data.datalist
              // 将页码重置为后台传过来的page
              this.page = res.data.pagecond.page
              this.total = res.data.pagecond.count
              // 处理数据
              if (this.page === 1) {
                this.list = resData
              } else {
                this.list = this.list.concat(resData)
              }
            	// 没有返回数据, 或返回的数据为空, 结束加载
              if (!resData || resData.length === 0) {
                this.finished = true
                return
              }
              return res
            }).catch(res => {
              // 接口请求报错, 结束请求, 给出报错信息
              this.finished = true
              this.$toast(res.message)
            }).finally(() => {
              // 当前是否需要累加页码,如删除,修改等操作,可能需要操作后仍查看操作页数据,此时不累加。在引用组件的执行方法前设置							 isKeepPage为true
              this.isKeepPage ? '' : this.page++
              // 重置状态值
              this.refreshing = false
              this.loading = false
              // 返回数据为空或最后一页不足分页条数或当前数据长度与数据总长度相等即没有数据了
              this.finished = this.list.length >= this.total ? true : false
              // 清除loading
              this.$toast.clear()
            })
          } else {
            // 不满足获取数据条件,重置状态值,且此时finished为true
            this.finished = true
            this.refreshing = false
            this.loading = false
          }
        },
    
        // 下拉刷新
        onRefresh () {
          // 只重置页码,不清空列表,直接覆盖数据
          this.page = 1
          // 重置状态, 此时finished为false, 在onLoad中再次判断状态
          this.finished = false
          this.loading = true
          // 重新加载数据
          this.onLoad()
          this.refreshing = false
        }
      }
    }
    
    
  • template

    <!-- html -->
    
    <template>
      <div class="outer">
    
        <van-pull-refresh
          v-model="refreshing"
          success-text="刷新成功"
          @refresh="onRefresh"
        >
          <van-list
            v-model="loading"
            :finished="finished"
            :immediate-check="false"
            :finished-text="list.length === 0 ? '' : '没有更多了'"
            error-text="请求失败,点击重新加载"
            @load="onLoad"
          >
    
            <van-tabs
              v-model="active"
              sticky
              animated
              color="#0061FF"
              title-active-color="#121C30"
              @change="changeTab"
              >
              <van-tab
                v-for="item in tabList"
                :key="item.index"
                :title="`${item.name}(${item.count})`"
                :name="item.label"
              >
    
                <van-search
                  v-model="searchData"
                  clearable
                  placeholder="请输入金额"
                  @clear="onClear"
                  @search="onSearch"
                  @cancel="onCancel"
                />
    
                <div
                  class="item"
                  v-for="ele in list"
                  :key="ele.index"
                  @click="toDetail(ele)"
                >
    
                  <!-- 需要循环的list内容 -->
                  
                </div>
    
                <div v-if="list.length === 0" class="empty">
                  <img class="image" :src="" />
                  <p class="text mt-20">暂无数据</p>
                </div>
    
              </van-tab>
            </van-tabs>
    
          </van-list>
        </van-pull-refresh>
    
      </div>
    </template>
    
    
  • 组件内的获取list

    getList () {
      if (this.searchData !== '') {
        localStorage.setItem('searchData', this.searchData)
      }
      return new Promise((resolve, reject) => {
        const sendData = {
          page: this.page,
          pageSize: this.pageSize,
          // ...
        }
        getData(sendData).then(res => {
          if (res && res.code === '0') {
            // 处理下拉刷新 + 上拉加载外的其他操作
            // 当前tab数量修改
            let tabIndex = 0
            this.tabList.forEach((item, index) => {
              if (this.active === item.label) {
                tabIndex = index
              }
            })
            this.tabList[tabIndex].count = res.data.pagecond.count
            // 处理数据  
            resolve(res)
          } else {
            // 错误处理
            this.$toast(res.message)
          }
        }).catch(err => {
          // 错误处理, 此时finished要为true
          reject(err)
          this.finished = true
          this.refreshing = false
          this.loading = false
        })
      })
    }
    
  • 其他需要调用onRefresh的方法

    // 搜索和获取走的同一个接口, 直接调用onRefresh即可(list = 1后会重新覆盖数据)
    onSearch () {
      this.onRefresh()
    },
    // 获取tab对应的总数和数据是两个接口,再重新调用一下
    onCancel () {
      this.getCount()
      this.onRefresh()
    },
    // 切换tab时, 同搜索, 调用onRefresh即可
    changeTab () {
      localStorage.setItem('active', this.active)
      this.onRefresh()
    }
    
  • css样式

    .container {
      min-height: 100vh;
      overflow: auto;
      background: @bgr;
    }
    
  • 不需要改变页码的情况

    export default {
      mixins: [listMixin],
      doNotInit: true,
      data: {},
      methods: {},
      ...
    }
    

一些问题

  • 有数据,但是不滚动

  • 外层元素设置高度,并设置 overflow: auto

  • onLoad方法执行多次

    • immediate-check 属性 设置为 false
    • 设置 min-height: 100vh (移动端) 或 特定高度
    • refreshing 状态不对
  • refresh后 直接加载了所有数据,一直在累加页码重新获取

    • finished 状态不对
  • 下拉刷新 直接在页面中间下拉就触发了

    • 因为有两个滚动条,只是看不到而已,你触摸的是页面中间下拉刷新的滚动条,所以没办法返回到顶部,改成一个页面只有一个滚动条,把下拉刷新的布局在最外层就好了
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
你可以使用 Vant UI 库中的 `van-pull-refresh` 组件和 `van-list` 组件来实现下拉刷新和上拉加载的功能。 首先,确保你已经安装了 Vant UI 并成功引入了相关组件。然后,按照以下步骤进行操作: 1. 在页面中引入 `van-pull-refresh` 和 `van-list` 组件: ```html <template> <van-pull-refresh @refresh="onRefresh"> <van-list v-model="listData" :finished="finished" @load="onLoad"> <!-- 列表内容 --> </van-list> </van-pull-refresh> </template> ``` 2. 在页面的 `data` 中定义相关数据和方法: ```javascript export default { data() { return { listData: [], // 列表数据 finished: false, // 是否加载完所有数据 }; }, methods: { onRefresh() { // 下拉刷新回调函数 // 在这里执行刷新操作,比如重新从服务器获取最新数据 // 更新列表数据,并将 finished 设置为 false,表示还有更多数据可以加载 }, onLoad() { // 上拉加载回调函数 // 在这里执行加载更多操作,比如从服务器获取下一页数据 // 更新列表数据,并将 finished 设置为 true,表示没有更多数据可以加载 }, }, }; ``` 3. 在 `onRefresh` 和 `onLoad` 方法中,根据实际业务逻辑执行刷新和加载更多的操作。你可以根据自己的需求,调用接口获取数据并更新 `listData` 数组的内容。 这样,你就可以通过下拉刷新和上拉加载来实现列表数据的动态更新了。记得根据实际情况,在请求完成时设置 `finished` 的值,以便在页面中显示加载完成的状态。 希望对你有帮助!如有更多疑问,请随时提问。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值