基于vue2实现上拉加载功能


Posted in Javascript onNovember 28, 2017

本文实例为大家分享了vue2实现上拉加载展示的具体代码,供大家参考,具体内容如下

因为我们项目中,还用了swiper。很多都是滑动切换的,但是又得上拉加载,所以导致,很多UI框架,我们用了,都有不同的bug出现,没办法,最后写了一个。代码如下(这个因为很多地方会用,所以建议放在components/common下面):

<template>
  <div class="loadmore">
    <slot></slot>
    <slot name="bottom">
    </slot>
  </div>
</template>

<style>
  .loadmore{
    width:100%;
  }
</style>

<script>
  export default {
    name: 'loadmore',
    props: {
      maxDistance: {
        type: Number,
        default: 0
      },
      autoFill: {
        type: Boolean,
        default: true
      },
      distanceIndex: {
        type: Number,
        default: 2
      },
      bottomPullText: {
        type: String,
        default: '上拉刷新'
      },
      bottomDropText: {
        type: String,
        default: '释放更新'
      },
      bottomLoadingText: {
        type: String,
        default: '加载中...'
      },
      bottomDistance: {
        type: Number,
        default: 70
      },
      bottomMethod: {
        type: Function
      },
      bottomAllLoaded: {
        type: Boolean,
        default: false
      },
    },
    data() {
      return {
        // 最下面出现的div的位移
        translate: 0,
        // 选择滚动事件的监听对象
        scrollEventTarget: null,
        containerFilled: false,
        bottomText: '',
        // class类名
        bottomDropped: false,
        // 获取监听滚动元素的scrollTop
        bottomReached: false,
        // 滑动的方向  down---向下互动;up---向上滑动
        direction: '',
        startY: 0,
        startScrollTop: 0,
        // 实时的clientY位置
        currentY: 0,
        topStatus: '',
        // 上拉加载的状态  ''   pull: 上拉中
        bottomStatus: '',
      };
    },
    watch: {
      // 改变当前加载在状态
      bottomStatus(val) {
        this.$emit('bottom-status-change', val);
        switch (val) {
          case 'pull':
            this.bottomText = this.bottomPullText;
            break;
          case 'drop':
            this.bottomText = this.bottomDropText;
            break;
          case 'loading':
            this.bottomText = this.bottomLoadingText;
            break;
        }
      }
    },
    methods: {
      onBottomLoaded() {
        this.bottomStatus = 'pull';
        this.bottomDropped = false;
        this.$nextTick(() => {
          if (this.scrollEventTarget === window) {
          document.body.scrollTop += 50;
        } else {
          this.scrollEventTarget.scrollTop += 50;
        }
        this.translate = 0;
      });
        // 注释
        if (!this.bottomAllLoaded && !this.containerFilled) {
          this.fillContainer();
        }
      },

      getScrollEventTarget(element) {
        let currentNode = element;
        while (currentNode && currentNode.tagName !== 'HTML' &&
        currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {
          let overflowY = document.defaultView.getComputedStyle(currentNode).overflowY;
          if (overflowY === 'scroll' || overflowY === 'auto') {
            return currentNode;
          }
          currentNode = currentNode.parentNode;
        }
        return window;
      },
      // 获取scrollTop
      getScrollTop(element) {
        if (element === window) {
          return Math.max(window.pageYOffset || 0, document.documentElement.scrollTop);
        } else {
          return element.scrollTop;
        }
      },
      bindTouchEvents() {
        this.$el.addEventListener('touchstart', this.handleTouchStart);
        this.$el.addEventListener('touchmove', this.handleTouchMove);
        this.$el.addEventListener('touchend', this.handleTouchEnd);
      },
      init() {
        this.bottomStatus = 'pull';
        // 选择滚动事件的监听对象
        this.scrollEventTarget = this.getScrollEventTarget(this.$el);
        if (typeof this.bottomMethod === 'function') {
          // autoFill 属性的实现  注释
          this.fillContainer();
          // 绑定滑动事件
          this.bindTouchEvents();
        }
      },
      // autoFill 属性的实现  注释
      fillContainer() {
        if (this.autoFill) {
          this.$nextTick(() => {
            if (this.scrollEventTarget === window) {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
                document.documentElement.getBoundingClientRect().bottom;
          } else {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
                this.scrollEventTarget.getBoundingClientRect().bottom;
          }
          if (!this.containerFilled) {
            this.bottomStatus = 'loading';
            this.bottomMethod();
          }
        });
        }
      },
      // 获取监听滚动元素的scrollTop
      checkBottomReached() {
        if (this.scrollEventTarget === window) {
          return document.body.scrollTop + document.documentElement.clientHeight >= document.body.scrollHeight;
        } else {
          // getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。 right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。
          return this.$el.getBoundingClientRect().bottom <= this.scrollEventTarget.getBoundingClientRect().bottom + 1;
        }
      },
      // ontouchstart 事件
      handleTouchStart(event) {
        // 获取起点的y坐标
        this.startY = event.touches[0].clientY;
        this.startScrollTop = this.getScrollTop(this.scrollEventTarget);
        this.bottomReached = false;
        if (this.bottomStatus !== 'loading') {
          this.bottomStatus = 'pull';
          this.bottomDropped = false;
        }
      },
      // ontouchmove事件
      handleTouchMove(event) {
        if (this.startY < this.$el.getBoundingClientRect().top && this.startY > this.$el.getBoundingClientRect().bottom) {
          // 没有在需要滚动的范围内滚动,不再监听scroll
          return;
        }
        // 实时的clientY位置
        this.currentY = event.touches[0].clientY;
        // distance 移动位置和开始位置的差值    distanceIndex---
        let distance = (this.currentY - this.startY) / this.distanceIndex;
        // 根据 distance 判断滑动的方向 并赋予变量  direction down---向下互动;up---向上滑动
        this.direction = distance > 0 ? 'down' : 'up';
        if (this.direction === 'up') {
          // 获取监听滚动元素的scrollTop
          this.bottomReached = this.bottomReached || this.checkBottomReached();
        }
        if (typeof this.bottomMethod === 'function' && this.direction === 'up' &&
            this.bottomReached && this.bottomStatus !== 'loading' && !this.bottomAllLoaded) {
          // 有加载函数,是向上拉,有滚动距离,不是正在加载ajax,没有加载到最后一页
          event.preventDefault();
          event.stopPropagation();
          if (this.maxDistance > 0) {
            this.translate = Math.abs(distance) <= this.maxDistance
                ? this.getScrollTop(this.scrollEventTarget) - this.startScrollTop + distance : this.translate;
          } else {
            this.translate = this.getScrollTop(this.scrollEventTarget) - this.startScrollTop + distance;
          }
          if (this.translate > 0) {
            this.translate = 0;
          }
          this.bottomStatus = -this.translate >= this.bottomDistance ? 'drop' : 'pull';
        }
      },
      // ontouchend事件
      handleTouchEnd() {
        if (this.direction === 'up' && this.bottomReached && this.translate < 0) {
          this.bottomDropped = true;
          this.bottomReached = false;
          if (this.bottomStatus === 'drop') {
            this.translate = '-50';
            this.bottomStatus = 'loading';
            this.bottomMethod();
          } else {
            this.translate = '0';
            this.bottomStatus = 'pull';
          }
        }
        this.direction = '';
      }
    },
    mounted() {
      this.init();
    }
  };
</script>

然后哪个页面需要,在哪个页面导入即可:import LoadMore from './../common/loadmore.vue';在需要引入他的页面写法如下:

<template>
 <section class="finan">
  <!-- 上拉加载更多 -->
  <load-more
  :bottom-method="loadBottom"
  :bottom-all-loaded="allLoaded"
  :bottomPullText='bottomText'
  :auto-fill="false"
  @bottom-status-change="handleBottomChange"
  ref="loadmore">
    <div>
  这里写你需要的另外的模块
    </div>
    <div v-show="loading" slot="bottom" class="loading"> 这个div是为让上拉加载的时候显示一张加载的gif图
     <img src="./../../assets/main/uploading.gif">
    </div>
  </load-more>
 </section>
</template>

然后在此页面的data里和methods设置如下:

export default {
    name: 'FinancialGroup',
    props:{
 
    },
    data () {
      return {
        // 上拉加载数据
        scrollHeight: 0,
        scrollTop: 0,
        containerHeight: 0,
        loading: false,
        allLoaded: false,
        bottomText: '上拉加载更多...',
        bottomStatus: '',
        pageNo: 1,
        totalCount: '',
      }
    },
    methods: {
    /* 下拉加载 */
    _scroll: function(ev) {
      ev = ev || event;
      this.scrollHeight = this.$refs.innerScroll.scrollHeight;
      this.scrollTop = this.$refs.innerScroll.scrollTop;
      this.containerHeight = this.$refs.innerScroll.offsetHeight;
    },
    loadBottom: function() {
      this.loading = true;
      this.pageNo += 1;  // 每次更迭加载的页数
      if (this.pageNo == this.totalGetCount) {
        // 当allLoaded = true时上拉加载停止
        this.loading = false;
        this.allLoaded = true;
      }
      api.commonApi(后台接口,请求参数) 这个api是封装的axios有不懂的可以看vue2+vuex+axios那篇文章
          .then(res => {
        setTimeout(() => {
      要使用的后台返回的数据写在setTimeout里面
         this.$nextTick(() => {
          this.loading = false;
        })
      }, 1000)
     });
    },
    handleBottomChange(status) {
      this.bottomStatus = status;
    },
  }

这样就完成了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Firefox window.close()的使用注意事项
Apr 11 Javascript
jQuery中append、insertBefore、after与insertAfter的简单用法与注意事项
Apr 04 Javascript
javascript判断iphone/android手机横竖屏模式的函数
Dec 20 Javascript
jQuery判断checkbox是否选中的小例子
Dec 02 Javascript
Javascript学习笔记之数组的遍历和 length 属性
Nov 23 Javascript
js实现图片和链接文字同步切换特效的方法
Feb 20 Javascript
jQuery中(function($){})(jQuery)详解
Jul 15 Javascript
JavaScript的ExtJS框架中表格的编写教程
May 21 Javascript
利用Angularjs和Bootstrap前端开发案例实战
Aug 27 Javascript
微信小程序开发实战教程之手势解锁
Nov 18 Javascript
jQuery实现的上传图片本地预览效果简单示例
Mar 29 jQuery
浅入深出Vue之组件使用
Jul 11 Javascript
微信小程序模板和模块化用法实例分析
Nov 28 #Javascript
基于Vue的移动端图片裁剪组件功能
Nov 28 #Javascript
javaScript canvas实现(画笔大小 颜色 橡皮的实例)
Nov 28 #Javascript
基于Vue框架vux组件库实现上拉刷新功能
Nov 28 #Javascript
JavaScript中关于class的调用方法
Nov 28 #Javascript
基于vue+canvas的excel-like组件实例详解
Nov 28 #Javascript
JS原型继承四步曲及原型继承图一览
Nov 28 #Javascript
You might like
使用ob系列函数实现PHP网站页面静态化
2014/08/13 PHP
php获取根域名方法汇总
2014/10/28 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
setTimeout与setInterval在不同浏览器下的差异
2010/01/24 Javascript
将nodejs打包工具整合到鼠标右键的方法
2013/05/11 NodeJs
基于JavaScript获取鼠标位置的各种方法
2015/12/16 Javascript
JS+CSS实现下拉刷新/上拉加载插件
2017/03/31 Javascript
AngularJS中的拦截器实例详解
2017/04/07 Javascript
vue-router history模式下的微信分享小结
2018/07/05 Javascript
React 使用recharts实现散点地图的示例代码
2018/12/07 Javascript
Vue-Cli项目优化操作的实现
2019/10/27 Javascript
axios 实现post请求时把对象obj数据转为formdata
2019/10/31 Javascript
如何在JS文件中获取Vue组件
2020/09/16 Javascript
react ant Design手动设置表单的值操作
2020/10/31 Javascript
JavaScript基于SVG的图片切换效果实例代码
2020/12/15 Javascript
[58:59]完美世界DOTA2联赛PWL S3 access vs CPG 第一场 12.13
2020/12/16 DOTA
python 网络编程详解及简单实例
2017/04/25 Python
python中单例常用的几种实现方法总结
2018/10/13 Python
python3 json数据格式的转换(dumps/loads的使用、dict to str/str to dict、json字符串/字典的相互转换)
2019/04/01 Python
导入tensorflow时报错:cannot import name 'abs'的解决
2019/10/10 Python
pandas 强制类型转换 df.astype实例
2020/04/09 Python
python画图时设置分辨率和画布大小的实现(plt.figure())
2021/01/08 Python
Amaze UI 文件选择域的示例代码
2020/08/26 HTML / CSS
法国时尚童装网站:Melijoe
2016/08/10 全球购物
日本卡普空电视游戏软件公司官方购物网站:e-CAPCOM
2018/07/17 全球购物
Stio官网:男女、儿童户外服装
2019/12/13 全球购物
医学生自荐信
2013/12/03 职场文书
单位门卫岗位职责
2013/12/20 职场文书
银行内勤岗位职责
2014/04/09 职场文书
汽修专业自荐信
2014/07/07 职场文书
电子银行业务授权委托书
2014/10/10 职场文书
小学教师自我评价
2015/03/04 职场文书
oracle通过存储过程上传list保存功能
2021/05/12 Oracle
Redis中一个String类型引发的惨案
2021/07/25 Redis
如何打开Win11系统注册表编辑器?Win11注册表编辑器打开修复方法
2022/04/05 数码科技
vue-cli3.x配置全局的scss的时候报错问题及解决
2022/04/30 Vue.js