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入门—编写一个导航条(可伸缩)
Jan 07 Javascript
利用了jquery的ajax实现二级联互动菜单
Dec 02 Javascript
浅谈JavaScript字符串与数组
Jun 03 Javascript
js控住DOM实现发布微博效果
Aug 30 Javascript
微信小程序 wxapp内容组件 text详细介绍
Oct 31 Javascript
Javascript 两种刷新方法以及区别和适用范围
Jan 17 Javascript
Bootstrap警告框(Alert)插件使用方法
Mar 21 Javascript
jQuery插件FusionCharts绘制的2D条状图效果【附demo源码】
May 13 jQuery
JavaScript如何对图片进行黑白化
Apr 10 Javascript
微信小程序自定义组件components(代码详解)
Oct 21 Javascript
JavaScript 引用类型实例详解【数组、对象、严格模式等】
May 13 Javascript
vscode+gulp轻松开发小程序的完整步骤
Oct 18 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
ExtJS与PHP、MySQL实现存储的方法
2010/04/02 PHP
PHP在线生成二维码代码(google api)
2013/06/03 PHP
php 强制下载文件实现代码
2013/10/28 PHP
PHP实现多图上传(结合uploadify插件)思路分析
2016/11/30 PHP
PHP使用pdo连接access数据库并循环显示数据操作示例
2018/06/05 PHP
php用xpath解析html的代码实例讲解
2019/02/14 PHP
使用jQuery的将桌面应用程序引入浏览器
2010/11/19 Javascript
js 在定义的时候立即执行的函数表达式(function)写法
2013/01/16 Javascript
jQuery动画效果图片轮播特效
2016/01/12 Javascript
原生JavaScript实现滚动条效果
2020/03/24 Javascript
JS设置cookie、读取cookie
2016/02/24 Javascript
javascript深拷贝(deepClone)详解
2016/08/24 Javascript
基于MVC+EasyUI的web开发框架之使用云打印控件C-Lodop打印页面或套打报关运单信息
2016/08/29 Javascript
js控住DOM实现发布微博效果
2016/08/30 Javascript
js实现文本上下来回滚动
2017/02/03 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
2017/02/21 Javascript
javascript实现数据双向绑定的三种方式小结
2017/03/09 Javascript
ionic中的$ionicPlatform.ready事件中的通用设置
2017/06/11 Javascript
JavaScript截屏功能的实现代码
2017/07/28 Javascript
layui中的switch开关实现方法
2019/09/03 Javascript
vue 导航菜单刷新状态不消失,显示对应的路由界面操作
2020/08/06 Javascript
[01:38]完美世界高校联赛决赛花絮
2018/12/02 DOTA
浅谈编码,解码,乱码的问题
2016/12/30 Python
python实现对excel进行数据剔除操作实例
2017/12/07 Python
python实现类之间的方法互相调用
2018/04/29 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
Python自动抢红包教程详解
2019/06/11 Python
python实现对变位词的判断方法
2020/04/05 Python
如何在python中执行另一个py文件
2020/04/30 Python
python 统计list中各个元素出现的次数的几种方法
2021/02/20 Python
StubHub智利:购买和出售您的门票
2016/11/23 全球购物
美国男士内衣品牌:Tommy John
2017/12/22 全球购物
印度在线购物网站:Paytmmall
2019/07/24 全球购物
生产工厂门卫岗位职责
2014/09/26 职场文书
2015驻村干部工作总结
2015/04/07 职场文书
廉洁自律证明
2015/06/24 职场文书