移动端分页滚动加载

文章介绍了vant组件List的使用,包括上拉加载、自定义分页器、模仿京东商品列表的已浏览数提示以及返回顶部功能。通过监听滚动事件实现了滚动相关功能的动态更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、vant组件List(完整)

<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
  <van-list
    v-model="loading"
    :finished="finished"
    finished-text="没有更多了"
    :error.sync="error"
    error-text="请求失败,点击重新加载"
    @load="onLoad"
  >
    // 列表项 <div class="batchItem" v-for="item in batchList" :key="item.pcbzid"></div>
  </van-list>
</van-pull-refresh>
refreshing: false,
loading: false,
error: false,
finished: false,
async onLoad() {
  if (this.refreshing) {
    this.batchList = [];
    this.pageNum = 1;
    this.refreshing = false;
  }
  try {
    await this.getBatchList();
    this.loading = false;
    console.log(this.batchList.length, this.total);
    // 数据全部加载完成
    if (this.batchList.length >= this.total) {
      this.finished = true;
    }
  } catch (err) {
    this.error = true;
  } finally {
    this.loading = false;
  }
},
onRefresh() {
  // 清空列表数据
  this.finished = false;
  // 重新加载数据
  // 将 loading 设置为 true,表示处于加载状态
  this.loading = true;
  this.onLoad();
},

上拉加载事件:

  • List 初始化后会触发一次 load 事件,加载第一屏数据,该特性可以通过immediate-check属性关闭。
  • 当loading为true时,不会触发load事件;load事件自动将loading改为true;故load事件结束后,要手动改loading为false;当loading为false时,会检测触底距离,调用load事件。
  • finished为true后,将不会触发load事件。

错误提示事件:

  • 当load事件加载失败后,手动改error为true,并将loading改为false。

下拉刷新事件:

  • 意味着清空当前列表,还原初始化参数,加载第一屏数据 。
  • 当下拉超过一定距离,自动改refresh为true,调用refresh事件,结束后,手动改refresh为false。

二、自定义分页器(简易上拉加载)

概念理解:

  • 页面滚动距离/网页顶部被卷去高度(+)        scrollTop        document.documentElement.scrollTop || document.body.scrollTop
  • 可视窗口高度        windowHeight        document.documentElement.clientHeight || document.body.clientHeight
  • 滚动条总高度        scrollHeight        document.documentElement.scrollHeight || document.body.scrollHeight
  • 列表距离可视窗口顶部        listOffset        this.$refs.vanlist.getBoundingClientRect().top
  • 列表高度        listHeight        this.$refs.vanlist.clientHeight

在加载第一屏数据后滚动,只有scrollTop、listOffset会变

当 scrollTop + windowHeight = scrollHeight 时,说明当前滚动条已经到达底部

<div class="title">我是筛选条件区域</div>
<div ref="vanlist">
  <p v-for="item in list" :key="item">{{ item }}</p>
</div>
page: 1,//加载页数
list: 10,
isRefreshUnLock: true,//防止多次触底,频繁加载
  mounted() {
    window.addEventListener("scroll", this.handleScroll);
  },
  destroyed() {
    window.removeEventListener("scroll", this.handleScroll);
  },
  methods: {
    handleScroll() {
      let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; 
      let windowHeight = document.documentElement.clientHeight || document.body.clientHeight; 
      let scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
      let listOffset = this.$refs.vanlist.getBoundingClientRect().top;
      let listHeight = this.$refs.vanlist.clientHeight;

      // console.log("scrollTop", scrollTop);
      // console.log("windowHeight", windowHeight);
      // console.log("scrollHeight", scrollHeight);
      // console.log("距离顶端的距离", listOffset); //顶端是可视窗口顶端
      // console.log("list高度", listHeight);

      //滚动条距离底部小于等于50,且当前不在加载状态时 =》 加载更多数据
      if (scrollTop + windowHeight >= scrollHeight - 50 && this.isRefreshLock) {
        this.isRefreshUnLock = false;
        setTimeout(() => {
          this.list += 10;
          this.isRefreshUnLock = true;
          this.page++;
        }, 3000);
      }
    }
  }

补充:自定义的话,除了监听scroll事件,还可以使用IntersectionObserve这个API实现

参考: 移动端滚动分页解决方案 - 掘金


 三、模仿京东商品列表页的已浏览数与返回顶部(van-list)

当第一屏数据完全滚出画面后,页面右下角出现提示:

当页面处于滚动状态,提示已浏览数/总数;当页面处于静止状态,提示返回顶部的标识。

 

1. 页面结构:

    <!-- 搜索框在滚动时会吸附在顶部 navHeight -->
    <van-sticky> <div ref="navHeight"></div> </van-sticky>
    <!-- 可滚动区域 moveContent:条件查询 condition + 列表 vanlist -->
    <div ref="moveContent">
      <div ref="condition"></div>
      <van-pull-refresh> <van-list> </van-list> </van-pull-refresh>
    </div>
    <!-- 右下角提示内容 -->
    <div class="fixPart" v-show="isScroll">
      <div v-show="isPage"> <span>{{ num }}</span ><span>/{{ total }} </span> </div>
      <div v-show="!isPage" @click="backTop"><van-icon name="back-top"/></div>
    </div>

 2. 要先实现监听滚动,并检测滚动停止:

滚动事件中记录当前滚动开始位置SA,开启延时器,延时事件中记录当下滚动结束位置SB,比较SA与SB,判断是否处于滚动状态。

      watchScrollTimer: null, //监听滚动定时器
      scrollT: 0,             //滚动开始位置,
      stopscroll: 0,          //滚动结束位置
      isPage: true,           //显示浏览数 / 返回顶部
      isScroll: false,        //显示右下角提示
  methods: {    
    handleScroll() {
      clearTimeout(this.watchScrollTimer); //清除监听滚动定時器
      this.watchScrollTimer = setTimeout(this.scrollEnd, 500);
      this.scrollT = document.documentElement.scrollTop || document.body.scrollTop;
      this.isPage = true;
      // .......
    },
    scrollEnd() {
      this.stopscroll = document.documentElement.scrollTop || document.body.scrollTop;
      // 判断当前处于静止或滚动状态
      if (this.stopscroll == this.scrollT) {
        console.log("滚动已结束");
        this.isPage = false;
      }
    },
  }
  mounted() {
    window.addEventListener("scroll", this.handleScroll);
  },
  destroyed() {
    window.removeEventListener("scroll", this.handleScroll);
    clearInterval(this.watchScrollTimer); // 清除定时器
    this.watchScrollTimer = null;
  },

3. 判断浏览个数:

      num: 0,           //已浏览个数
      total: 0,         //商品总数
  handleScroll() {
      // ......
      let windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
      let navHeight = this.$refs.navHeight.clientHeight;
      let moveOffset = this.$refs.moveContent.getBoundingClientRect().top; //要滚动内容距顶端距离
      let moveHeight = this.$refs.moveContent.clientHeight;                //要滚动内容的高度
      let conditionHeght = this.$refs.condition.clientHeight;              //查询条件的高度
      let listOffset = moveOffset + conditionHeght;
      let listHeight = moveHeight - conditionHeght;
      // 总结:牵扯这么多距离,就是为了得到列表List自身的高度,与窗口顶端的距离

      // 判断浏览数
      if (listOffset >= navHeight) {
        // 只要列表距离顶部的距离大于吸附元素的高度 =》 页面上列表没有被吸附元素遮挡 =》 浏览数认定1
        this.num = 1;
      } else {
        // 只要遮挡了,开始计算当前被遮挡的是第几位,即浏览数为几
        let single = listHeight / this.list.length; // 100为css样式设定的
        this.num = -Math.ceil((listOffset - navHeight) / single) + 1;
      }

      // 意图第一屏数据滚出窗口 即 滚动距离等于窗口高度的时候,显示右下角提示;但这里判断太粗糙,不精确
      // 其实想要出现提示的时机很随意,可以自己把握
      if (listOffset < -windowHeight) {
        this.isScroll = true;
      } else {
        this.isScroll = false;
      }
    },

4. 返回顶部 :

    backTop() {
      document.documentElement.scrollTop = 0;
      document.body.scrollTop = 0;
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值