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 相关文章推荐
for 循环性能比较 提高for循环的效率
Mar 19 Javascript
js 获取中文拼音,Select自动匹配字母获取值的代码
Sep 23 Javascript
Flex通过JS获取客户端IP和计算机名的实例代码
Nov 21 Javascript
JQuery实现绚丽的横向下拉菜单
Dec 19 Javascript
Vue 多层组件嵌套二种实现方式(测试实例)
Sep 08 Javascript
js中json对象和字符串的理解及相互转化操作实现方法
Sep 22 Javascript
详解vue mint-ui源码解析之loadmore组件
Oct 11 Javascript
React中的refs的使用教程
Feb 13 Javascript
vue父组件异步获取数据传给子组件的方法
Jul 26 Javascript
基于Angularjs-router动态改变Title值的问题
Aug 30 Javascript
JavaScript实现汉字转换为拼音及缩写的方法示例
Mar 28 Javascript
js实现盒子滚动动画效果
Aug 09 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
php5.2时间相差8小时
2007/01/15 PHP
解决CodeIgniter伪静态失效
2014/06/09 PHP
php绘制一个扇形的方法
2015/01/24 PHP
Adnroid 微信内置浏览器清除缓存
2016/07/11 PHP
YII2 实现多语言配置的方法分享
2017/01/11 PHP
php curl批处理实现可控并发异步操作示例
2018/05/09 PHP
php实现映射操作实例详解
2019/10/02 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
JS实现简单路由器功能的方法
2015/05/27 Javascript
可以浮动某个物体的jquery控件用法实例
2015/07/24 Javascript
初识angular框架后的所思所想
2016/02/19 Javascript
以WordPress为例讲解jQuery美化页面Title的方法
2016/05/23 Javascript
JS添加或修改控件的样式(Class)实现方法
2016/10/15 Javascript
MUI  Scroll插件的使用详解
2017/04/13 Javascript
使用JS实现气泡跟随鼠标移动的动画效果
2017/09/16 Javascript
vue项目打包部署到服务器的方法示例
2018/08/27 Javascript
微信小程序实现多选功能
2018/11/04 Javascript
原生javascript的ajax请求及后台PHP响应操作示例
2020/02/24 Javascript
js禁止查看源文件屏蔽Ctrl+u/s、F12、右键等兼容IE火狐chrome
2020/10/01 Javascript
[54:06]OG vs TNC 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python字符串逆序输出的实例讲解
2019/02/16 Python
Python selenium根据class定位页面元素的方法
2019/02/26 Python
详解python中init方法和随机数方法
2019/03/13 Python
Keras Convolution1D与Convolution2D区别说明
2020/05/22 Python
python实现在列表中查找某个元素的下标示例
2020/11/16 Python
html5 canvas移动浏览器上实现图片压缩上传
2016/03/11 HTML / CSS
美国家居装饰网上商店:Lulu & Georgia
2019/09/14 全球购物
Fox Racing英国官网:越野摩托车和山地自行车服装
2020/02/26 全球购物
俄罗斯药房连锁店:ASNA
2020/06/20 全球购物
企业党员公开承诺书
2014/03/26 职场文书
2014党的群众路线教育实践活动总结材料
2014/10/31 职场文书
初中成绩单评语
2014/12/29 职场文书
单位实习介绍信
2015/05/05 职场文书
聚众斗殴罪辩护词
2015/05/21 职场文书
八月迷情观后感
2015/06/11 职场文书
mysql的数据压缩性能对比详情
2021/11/07 MySQL