学习笔记-Vue.js 上拉翻页、下拉刷新

其实总体来说平,下拉刷新要比上拉翻页复杂的对。

上拉翻页只需判断是否到达pageHeight - viewportHeight - scrollHeight = 0 的临界条件,不需要细致的判断touch问题。

下拉刷新复杂是因为除了要判断到达scrollTop = 0 (页面在顶部)的临界条件外还需继续判断是否做的是下拉动作

下拉刷新

主要思路

  1. 最初touch时的Y坐标以及scrollTop的位置;
  2. 再将touching这个开关打开;(touchmove只要页面移动就会触发,因此需要设置一个开关touching来进行约束);
  3. 当touching为false或者scrollTop初始位置不在页面最顶端时,都不会继续将函数进行下去,这都不是下拉刷新的动作;
  4. 接下来计算移动距离并进行判断是否应当刷新

tips:

  • scrollTop 可以理解为当前滚动条的位置
  • state为0未开始,state为2正在刷新

touchstart touchmove touchend部分

// 绑定touchstart
    touchStart(e) {
      // 记录下触碰的Y坐标
      this.startY = e.targetTouches[0].pageY;
      // 记录下最开始scrolltop的位置,后面用来判断下拉情况是否应该刷新
      this.startScroll = document.scrollingElement.scrollTop || 0;
      // 任务move都会引起touchMove,增加开关
      this.touching = true;
    },

    // 绑定touchmove
    touchMove(e) {
      // 设置条件,只有当开关为true且起始点击scrolltop为0时才能继续运行函数
      if (!this.touching || document.documentElement.scrollTop > 0) {
        return;
      }

      // 计算移动的距离并判断
      let diff = e.targetTouches[0].pageY - this.startY - this.startScroll;
      if (diff > 0) {
        e.preventDefault();
      }
      this.top = Math.floor(diff * 0.25) + (this.state === 2 ? 40 : 0);
      // 改变顶部div的显隐状态和里面的话
      if (this.top >= 40) {
        this.loadWords = "正在刷新";
        this.isLoadMoreShow = true;
      }
    },

    // 绑定touchend
    touchEnd() {
      this.touching = false;
      // 在刷新状态中
      if (this.state === 2) {
        this.state = 2;
        this.top = this.offset;
        return;
      }
      // 执行刷新
      if (this.top >= 40) {
        this.refresh();
      } else {
        this.state = 0;
        this.top = 0;
      }
      // 判断touch松开后,是否为翻页动作
      this.scrollFn();
    },

刷新部分

此部分只是用来进行模拟刷新。

refresh: function() {
      this.loadWords = "刷新成功";
      this.data = [];
      for (let i = 0; i < 20; i++) {
        this.data.push({
          headshot:
            "https://tse1.mm.bing.net/th?id=OIP.7tHmoR_mte6veEPpG4dpRgAAAA&pid=Api&w=350&h=320&rs=1",
          name: "知乎知乎" + i,
          images: [
            "http://p0.qhimgs4.com/t014104515001404918.jpg",
            "http://p0.qhimgs4.com/t014104515001404918.jpg"
          ],
          words:
            "用三张图说明一切,前方高能!!!!!!胆小者、心理承受能力差的就别忘下看了。(抱歉抱歉抱歉抱歉,你们在。。。)",
          starNum: 11100 - i * 100,
          commentNum: 2400 - i * 100
        });
      }
      this.page.data = [];
      this.page.pageNum = 1;
      this.getPageData();
      this.isLoadMoreShow = false;
    },

上拉翻页

当pageHeight - viewportHeight - scrollHeight == 0 (pos == 0)的时候就代表整个页面到达了底部,代码中的判断条件pos < 20 ,也正是利用了这一点。在这里插入图片描述

翻页前需要将数据先进行分页

getPageData: function() {
      // 获得start 和 end 的值
      let start = this.page.pageSize * (this.page.pageNum - 1);
      let end = start + this.page.pageSize;
      if (end > this.page.totalCount) {
        end = this.page.totalCount;
      }
      // page.data增加数据
      const curPageData = this.data.slice(start, end);
      this.page.data = this.page.data.concat(curPageData);
    }

翻页动作

// 判定翻页动作
    scrollFn: function() {
      // 真实内容的高度
      let pageHeight = Math.max(
        document.body.scrollHeight,
        document.body.offsetHeight
      );

      // 视窗的高度
      let viewportHeight =
        window.innerHeight ||
        document.documentElement.clientHeight ||
        document.body.clientHeight ||
        0;

      // 隐藏的高度
      let scrollHeight =
        window.pageYOffset ||
        document.documentElement.scrollTop ||
        document.body.scrollHeight ||
        0;

      let pos = pageHeight - viewportHeight - scrollHeight;
      if (pos < 20 && this.startScroll > 0) {
        this.nextPage();
      }
    },
    
    
// 下一页
    nextPage: function() {
      // 判断是否是最后一项
      if (this.page.pageNum === this.page.totalPageNum) {
        this.loadMoreing = false;
        return;
      }
      // 判断是否正在加载数据
      if (this.loadding) {
        return;
      }
      //开启数据
      this.loadding = true;
      this.page.pageNum++;
      let scrollHeight = document.body.scrollHeight;
      setTimeout(() => {
        this.getPageData();
        this.loadding = false;
        Vue.nextTick(function() {
          // DOM 滚动到上次内容最后位置
          document.documentElement.scrollTop = scrollHeight;
        });
      }, 1000);
    },

其他代码

这些都是在Vue框架下实现的,其他部分代码如下

data: function() {
    let data = [];
    for (let i = 0; i < 20; i++) {
      data.push({
        headshot:
          "https://tse1.mm.bing.net/th?id=OIP.7tHmoR_mte6veEPpG4dpRgAAAA&pid=Api&w=350&h=320&rs=1",
        name: "知乎知乎" + i,
        images: [
          "http://p0.qhimgs4.com/t014104515001404918.jpg",
          "http://p0.qhimgs4.com/t014104515001404918.jpg"
        ],
        words:
          "用三张图说明一切,前方高能!!!!!!胆小者、心理承受能力差的就别忘下看了。(抱歉抱歉抱歉抱歉,你们在。。。)",
        starNum: 11100 - i * 100,
        commentNum: 2400 - i * 100
      });
    }

    return {
      data: data,
      top: 0,
      state: 0,
      startY: 0, //保存开始滑动时,y轴位置
      startScroll: 0,
      touching: false,
      isLoadMoreShow: false,
      loadWords: "正在刷新",

      page: {
        totalCount: 0,
        totalPageNum: 0,
        pageSize: 3,
        pageNum: 1,
        data: []
      },
      loadding: false,
      loadMoreing: true
    };
  },

代码都取自做的一个知乎的小demo

github地址:https://github.com/RemEb/zhihu-web

代码参考部分网上资料,也进行了修改,还有很多地方可以完善。。

Logo

前往低代码交流专区

更多推荐