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 相关文章推荐
jQuery 锚点跳转滚动条平滑滚动一句话代码
Apr 30 Javascript
jquery事件机制扩展插件 jquery鼠标右键事件。
Dec 26 Javascript
js之onload事件的一点使用心得
Aug 14 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
Mar 14 Javascript
快速掌握Node.js模块封装及使用
Mar 21 Javascript
Three.js学习之网格
Aug 10 Javascript
详解Javascript中的原型OOP
Oct 12 Javascript
easyUI实现(alert)提示框自动关闭的实例代码
Nov 07 Javascript
JavaScript触发onScroll事件的函数节流详解
Dec 14 Javascript
JS实现线性表的链式表示方法示例【经典数据结构】
Apr 11 Javascript
React教程之封装一个Portal可复用组件的方法
Jan 02 Javascript
手动用webpack搭建第一个ReactApp的示例
Apr 11 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
php实现aes加密类分享
2014/02/16 PHP
php中调用其他系统http接口的方法说明
2014/02/28 PHP
PHP实现获取图片颜色值的方法
2014/07/11 PHP
Laravel事件监听器用法实例分析
2019/03/12 PHP
laravel解决迁移文件一次删除创建字段报错的问题
2019/10/24 PHP
Jquery替换已存在于element上的event的方法
2010/03/09 Javascript
JS控件的生命周期介绍
2012/10/22 Javascript
引用外部js乱码问题分析及解决方案
2013/04/12 Javascript
jQuery移除元素自动解绑事件实现思路及代码
2014/05/31 Javascript
JavaScript实现的一个计算数字步数的算法分享
2014/12/06 Javascript
angular.element方法汇总
2015/01/07 Javascript
jquery选择器简述
2015/08/31 Javascript
JavaScript实战之带收放动画效果的导航菜单
2016/08/16 Javascript
Node.js学习入门
2017/01/03 Javascript
基于Vue实现tab栏切换内容不断实时刷新数据功能
2017/04/13 Javascript
jQuery事件_动力节点Java学院整理
2017/07/05 jQuery
分享19个JavaScript 有用的简写写法
2017/07/07 Javascript
JavaScript函数绑定用法实例分析
2017/11/14 Javascript
ES6关于Promise的用法详解
2018/05/07 Javascript
vue项目中引入Sass实例方法
2019/08/27 Javascript
微信跳一跳辅助python代码实现
2018/01/05 Python
python实现堆和索引堆的代码示例
2018/03/19 Python
python用for循环求和的方法总结
2019/07/08 Python
django ajax发送post请求的两种方法
2020/01/05 Python
Python 爬虫性能相关总结
2020/08/03 Python
详解torch.Tensor的4种乘法
2020/09/03 Python
Javascript 高级手势使用介绍
2013/04/21 HTML / CSS
localStorage的过期时间设置的方法详解
2018/11/26 HTML / CSS
纽约海:Sea New York
2018/11/04 全球购物
2015年财务个人工作总结范文
2015/05/22 职场文书
三八红旗手主要事迹材料
2015/11/04 职场文书
教师学习中国梦心得体会
2016/01/05 职场文书
实用求职信模板范文
2019/05/13 职场文书
Nginx+SpringBoot实现负载均衡的示例
2021/03/31 Servers
使用 MybatisPlus 连接 SqlServer 数据库解决 OFFSET 分页问题
2022/04/22 SQL Server
Python 统计序列中元素的出现频度
2022/04/26 Python