vue loadmore 组件滑动加载更多源码解析


Posted in Javascript onJuly 19, 2017

上一篇讲到在项目中使用上拉加载更多组件,但是由于实际项目开发中由于需求变更或者说在webview中上拉加载有些机型在上拉时候会把webview也一起上拉导致上拉加载不灵敏等问题,我们有时候也会换成滑动到底部自动加载的功能。

既然都是加载更多,很多代码思想势必相似,主要区别在于上拉和滑动到底部这个操作上,所以,我们需要注意:

上拉加载是point指针touch触摸事件,现在因为是滑动加载,需要添加scroll事件去监听然后执行相应回调

上拉加载主要计算触摸滚动距离,滑动加载主要计算container底部和视窗上边缘的距离

事件绑定改成: 

mounted() {
  ···
  this.dom.addEventListener('scroll', this.scroll, false)
  ···
 },
 beforeDestroy() {
  ···
  this.dom.removeEventListener('scroll', this.scroll, false)
  ···
 },

事件回调改为:

/**
  * 滚动钩子
  */
  scroll() {
  const viewHeight = global.innerHeight
  let parentNode
  if (this.container !== global) {
   parentNode = this.$el
  } else {
   parentNode = this.$el.parentNode
  }
  if (parentNode) {
   // 获取Vue实例使用的根 DOM 元素相对于视口的位置
   const rect = parentNode.getBoundingClientRect()
   // this.distance 离底部多少距离开始加载
   // 如果此元素底边距离视口顶部的距离小于视口高度加上distance之和,就加载下一页
   if ((rect.bottom <= viewHeight + this.distance) && this.loadable && !this.loading) {
   this.load()
   }
  }
  },

源码如下:

<template>
 <div class="loadmore" ref="loadmore">
 <div class="loadmore__body">
  <slot></slot>
 </div>
 <div class="loadmore__footer">
  <span v-if="loading">
  <i class="tc-loading"></i>
  <span>正在加载</span>
  </span>
  <span v-else-if="loadable">加载更多</span>
  <span v-else>没有更多了</span>
 </div>
 </div>
</template>
<script type="text/babel">
 import axios from 'axios'
 const CancelToken = axios.CancelToken
 export default {
 data() {
  return {
  /**
   * 总页数(由服务端返回)
   * @type {number}
   */
  count: 0,
  /**
   * 是否正在拖拽中
   * @type {boolean}
   */
  dragging: false,
  /**
   * 已加载次数
   * @type {number}
   */
  times: 0,
  /**
   * 已开始记载
   * @type {boolean}
   */
  started: false,
  /**
   * 正在加载中
   * @type {boolean}
   */
  loading: false,
  dom: null,
  }
 },
 props: {
  /**
  * 初始化后自动开始加载数据
  */
  autoload: {
  type: Boolean,
  default: true,
  },
  /**
  * 离组件最近的可滚动父级元素(用于监听事件及获取滚动条位置)
  */
  container: {
  // Selector or Element
  default: () => (global),
  },
  /**
  * Axios请求参数配置对象
  * {@link https://github.com/mzabriskie/axios#request-config}
  */
  options: {
  type: Object,
  default: null,
  },
  /**
  * 起始页码
  */
  page: {
  type: Number,
  default: 1,
  },
  /**
  * 每页加载数据条数
  */
  rows: {
  type: Number,
  default: 10,
  },
  /**
  * 数据加载请求地址
  */
  url: {
  type: String,
  default: '',
  },
  /**
  * 距离底部多远加载
  */
  distance: {
  type: Number,
  default: 200,
  },
 },
 computed: {
  /**
  * 是否可以加载
  * @returns {boolean} 是与否
  */
  loadable() {
  return !this.started || (this.page + this.times) <= this.count
  },
 },
 mounted() {
  if (this.container !== global) {
  this.dom = document.querySelector(this.container)
  } else {
  this.dom = this.container
  }
  if (!this.dom) {
  return
  }
  this.dom.addEventListener('scroll', this.scroll, false)
  if (this.autoload && !this.loading) {
  this.load()
  }
 },
 // eslint-disable-next-line
 beforeDestroy() {
  if (this.dom) {
  this.dom.removeEventListener('scroll', this.scroll, false)
  }
 },
 methods: {
  /**
  * 滚动钩子
  */
  scroll() {
  const viewHeight = global.innerHeight
  let parentNode
  if (this.container !== global) {
   parentNode = this.$el
  } else {
   parentNode = this.$el.parentNode
  }
  if (parentNode) {
   const rect = parentNode.getBoundingClientRect()
   if ((rect.bottom <= viewHeight + this.distance) && this.loadable && !this.loading) {
   this.load()
   }
  }
  },
  /**
  * 加载一组数据的方法
  */
  load() {
  if (this.loading) {
   return
  }
  this.started = true
  this.loading = true
  const params = {
   currentPage: this.page + this.times,
   pageSize: this.rows,
  }
  const options = Object.assign({}, this.options, {
   url: this.url,
   cancelToken: new CancelToken((cancel) => {
   this.cancel = cancel
   }),
  })
  if (String(options.method).toUpperCase() === 'POST') {
   options.data = Object.assign({}, options.data, params)
  } else {
   options.params = Object.assign({}, options.params, params)
  }
  this.$axios.request(options).then((res) => {
   const data = res.result
   this.times += 1
   this.loading = false
   this.count = data.pageCount
   this.$emit('success', data.list)
   this.$emit('complete')
  }).catch((e) => {
   this.loading = false
   this.$emit('error', e)
   this.$emit('complete')
  })
  },
  /**
  * 重置加载相关变量
  */
  reset() {
  this.count = 0
  this.times = 0
  this.started = false
  this.loading = false
  },
  /**
  *重新开始加载
  */
  restart() {
  this.reset()
  this.load()
  },
 },
 }
</script>

以上所述是小编给大家介绍的vue loadmore 组件滑动加载更多源码解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
打开新窗口关闭当前页面不弹出关闭提示js代码
Mar 18 Javascript
js获取IP和PcName(IE)在vs中可用
Aug 02 Javascript
js原型继承的两种方法对比介绍
Mar 30 Javascript
jQuery中;function($,undefined) 前面的分号的用处
Dec 17 Javascript
Bootstrap布局之栅格系统详解
Jun 13 Javascript
利用jQuery的动画函数animate实现豌豆发射效果
Aug 28 Javascript
基于jQuery实现的查看全文功能【实用】
Dec 11 Javascript
利用vue.js插入dom节点的方法
Mar 15 Javascript
JS非空验证及邮箱验证的实例
Aug 11 Javascript
JavaScript实现好看的跟随彩色气泡效果
Feb 06 Javascript
ant-design-vue按需加载的坑的解决
May 14 Javascript
微信小程序使用前置摄像头拍照
Oct 22 Javascript
JS实现的走迷宫小游戏完整实例
Jul 19 #Javascript
JS设置随机出现2个数字的实例代码
Jul 19 #Javascript
利用jQuery异步上传文件的插件用法详解
Jul 19 #jQuery
JavaScript 值类型和引用类型的初次研究(推荐)
Jul 19 #Javascript
基于bootstrap实现多个下拉框同时搜索功能
Jul 19 #Javascript
深入理解vue2.0路由如何配置问题
Jul 18 #Javascript
JavaScript实现二维坐标点排序效果
Jul 18 #Javascript
You might like
laravel 解决Validator使用中出现的问题
2019/10/25 PHP
PHP设计模式(四)原型模式Prototype实例详解【创建型】
2020/05/02 PHP
PHP中-&gt;和=&gt;的含义及使用示例解析
2020/08/06 PHP
RR vs IO BO3 第二场2.13
2021/03/10 DOTA
jQuery 学习6 操纵元素显示效果的函数
2010/02/07 Javascript
jQuery的remove()方法使用详解
2015/08/11 Javascript
JavaScript学习笔记之DOM基础 2.4
2015/08/14 Javascript
推荐10 个很棒的 jQuery 特效代码
2015/10/04 Javascript
jquery及js实现动态加载js文件的方法
2016/01/21 Javascript
boostrapTable的refresh和refreshOptions区别浅析
2017/01/22 Javascript
JS数组操作中的经典算法实例讲解
2017/07/26 Javascript
使用Bootstrap和Vue实现用户信息的编辑删除功能
2017/10/25 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
2018/01/05 Javascript
Vue动态控制input的disabled属性的方法
2018/06/26 Javascript
Vue在页面数据渲染完成之后的调用方法
2018/09/11 Javascript
基于Vue+Webpack拆分路由文件实现管理
2020/11/16 Javascript
[36:17]DOTA2上海特级锦标赛 - VGL音乐会全集
2016/03/06 DOTA
Python NumPy库安装使用笔记
2015/05/18 Python
使用httplib模块来制作Python下HTTP客户端的方法
2015/06/19 Python
Python中shape计算矩阵的方法示例
2017/04/21 Python
Python内置模块ConfigParser实现配置读写功能的方法
2018/02/12 Python
关于阿里云oss获取sts凭证 app直传 python的实例
2019/08/20 Python
Python 去除字符串中指定字符串
2020/03/05 Python
django的403/404/500错误自定义页面的配置方式
2020/05/21 Python
利用CSS3 动画 绘画 圆形动态时钟
2018/03/20 HTML / CSS
西班牙国家航空官方网站:Iberia
2017/11/16 全球购物
Hush Puppies澳大利亚官网:舒适的男女休闲和正装鞋
2019/08/24 全球购物
美国最大和最受信任的二手轮胎商店:Bestusedtires.com
2020/06/02 全球购物
战友聚会主持词
2014/04/02 职场文书
房屋买卖委托公证书
2014/04/08 职场文书
教师党员自我评议不足范文
2014/10/19 职场文书
22句经典语录:送给优柔寡断和胡思乱想的朋友们
2019/12/13 职场文书
JS新手入门数组处理的实用方法汇总
2021/04/07 Javascript
MySQL如何快速创建800w条测试数据表
2022/03/17 MySQL
JavaWeb Servlet开发注册页面实例
2022/04/11 Java/Android
python神经网络 使用Keras构建RNN训练
2022/05/04 Python