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 相关文章推荐
JavaScript类型系统之正则表达式
Jan 05 Javascript
jQuery实现带遮罩层效果的blockUI弹出层示例【附demo源码下载】
Sep 14 Javascript
JavaScript实现瀑布流以及加载效果
Feb 11 Javascript
Vue自定义指令详解
Jul 28 Javascript
详解vuex结合localstorage动态监听storage的变化
May 03 Javascript
微信小程序使用websocket通讯的demo,含前后端代码,亲测可用
May 22 Javascript
layUI实现列表查询功能
Jul 27 Javascript
JavaScript 斐波那契数列 倒序输出 输出100以内的质数代码实例
Sep 11 Javascript
解决layui中onchange失效以及form动态渲染失效的问题
Sep 27 Javascript
JS Ajax请求会话过期处理问题解决方法分析
Nov 16 Javascript
js实现消灭星星(web简易版)
Mar 24 Javascript
vue 防止页面加载时看到花括号的解决操作
Nov 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
php面向对象全攻略 (十四) php5接口技术
2009/09/30 PHP
解析array splice的移除数组中指定键的值,返回一个新的数组
2013/07/02 PHP
如何解决PHP使用mysql_query查询超大结果集超内存问题
2016/03/14 PHP
日期函数扩展类Ver0.1.1
2006/09/07 Javascript
用jquery来定位
2007/02/20 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
2012/02/16 Javascript
关于JavaScript中string 的replace
2013/04/12 Javascript
javascript date格式化示例
2013/09/25 Javascript
JavaScript中判断原生函数检查function是否是原生代码
2014/09/09 Javascript
JS实现的论坛Ajax打分效果完整实例
2015/10/31 Javascript
js实现异步循环实现代码
2016/02/16 Javascript
实现React单页应用的方法详解
2016/08/02 Javascript
漂亮! js实现颜色渐变效果
2016/08/12 Javascript
基于jQuery和Bootstrap框架实现仿知乎前端动态列表效果
2016/11/09 Javascript
jQuery.parseHTML() 函数详解
2017/01/09 Javascript
详解ElementUI之表单验证、数据绑定、路由跳转
2017/06/21 Javascript
Three.js实现简单3D房间布局
2018/12/30 Javascript
JS中async/await实现异步调用的方法
2019/08/28 Javascript
VUE 自定义组件模板的方法详解
2019/08/30 Javascript
NodeJS有难度的面试题(能答对几个)
2019/10/09 NodeJs
Angular+ionic实现折叠展开效果的示例代码
2020/07/29 Javascript
JavaScript中clientWidth,offsetWidth,scrollWidth的区别
2021/01/25 Javascript
彻底搞懂Python字符编码
2018/01/23 Python
Python字典对象实现原理详解
2019/07/01 Python
python创建n行m列数组示例
2019/12/02 Python
基于Python把网站域名解析成ip地址
2020/05/25 Python
python中使用.py配置文件的方法详解
2020/11/23 Python
HTML5的结构和语义(3):语义性的块级元素
2008/10/17 HTML / CSS
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
静心口服夜广告词
2014/03/20 职场文书
公司合作意向书
2014/04/01 职场文书
小学生期末评语大全
2014/04/21 职场文书
司法局火灾防控方案
2014/06/05 职场文书
工地安全标语
2014/06/07 职场文书
记账会计岗位职责
2014/06/16 职场文书
创先争优宣传标语
2014/10/08 职场文书