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 相关文章推荐
通过修改referer下载文件的方法
May 11 Javascript
childNodes.length与children.length的区别
May 14 Javascript
js如何设置在iframe框架中指定div不显示
Dec 04 Javascript
angular中的http拦截器Interceptors的实现
Feb 21 Javascript
使用jquery datatable和bootsrap创建表格实例代码
Mar 17 Javascript
React.js中常用的ES6写法总结(推荐)
May 09 Javascript
bootstrap confirmation按钮提示组件使用详解
Aug 22 Javascript
JS实现的计数排序与基数排序算法示例
Dec 04 Javascript
微信小程序实现给嵌套template模板传递数据的方式总结
Dec 18 Javascript
详解Webpack-dev-server的proxy用法
Sep 08 Javascript
构建大型 Vue.js 项目的10条建议(小结)
Nov 14 Javascript
Ant Design moment对象和字符串之间的相互转化教程
Oct 27 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
在任意字符集下正常显示网页的方法二(续)
2007/04/01 PHP
php 删除记录同时删除图片文件的实现代码
2010/05/12 PHP
php正则匹配html中带class的div并选取其中内容的方法
2015/01/13 PHP
php简单解析mysqli查询结果的方法(2种方法)
2016/06/29 PHP
PHP PDOStatement::setAttribute讲解
2019/02/01 PHP
PHP面向对象程序设计重载(overloading)操作详解
2019/06/13 PHP
js调试系列 控制台命令行API使用方法
2014/06/18 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
2015/09/01 Javascript
Javascript中apply、call、bind的巧妙使用
2016/08/18 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
Angular在一个页面中使用两个ng-app的方法
2017/02/20 Javascript
layui弹出层效果实现代码
2017/05/19 Javascript
深入讲解xhr(XMLHttpRequest)/jsonp请求之abort
2017/07/26 Javascript
Angular弹出模态框的两种方式
2017/10/19 Javascript
[15:57]教你分分钟做大人:斧王
2014/10/30 DOTA
[42:32]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
利用python批量检查网站的可用性
2016/09/09 Python
Python面向对象之继承代码详解
2018/01/29 Python
Python利用splinter实现浏览器自动化操作方法
2018/05/11 Python
利用Django-environ如何区分不同环境
2018/08/26 Python
django 自定义过滤器的实现
2019/02/26 Python
Python使用graphviz画流程图过程解析
2020/03/31 Python
虚拟环境及venv和virtualenv的区别说明
2021/02/05 Python
CSS3的first-child选择器实战攻略
2016/04/28 HTML / CSS
基于HTML5的WebGL经典3D虚拟机房漫游动画
2017/11/15 HTML / CSS
美国知名玩具品牌:Melissa & Doug
2016/08/16 全球购物
澳大利亚床上用品、浴巾和家居用品购物网站:Bambury
2020/04/16 全球购物
粗加工管理制度
2014/02/04 职场文书
安全教育月活动总结
2014/05/05 职场文书
省文明单位申报材料
2014/05/08 职场文书
教师党员个人整改措施
2014/10/27 职场文书
2015年度个人教学工作总结
2015/05/20 职场文书
信息技术研修心得体会
2016/01/08 职场文书
开学季:喜迎新生,迎新标语少不了
2019/11/07 职场文书
Python数据可视化之基于pyecharts实现的地理图表的绘制
2021/06/10 Python
动态规划之使用备忘录来改进Javascript函数
2022/04/07 Javascript