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乱码的一次解决过程 图解教程
Feb 20 Javascript
jQuery实现仿淘宝带有指示条的图片转动切换效果完整实例
Mar 04 Javascript
JavaScript中的getMilliseconds()方法使用详解
Jun 10 Javascript
Web打印解决方案之证件套打的实现思路
Aug 29 Javascript
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
Dec 15 Javascript
详解如何在Angular中快速定位DOM元素
May 17 Javascript
ES6深入理解之“let”能替代”var“吗?
Jun 28 Javascript
Vue2 SSR渲染根据不同页面修改 meta
Nov 20 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
Jun 28 Javascript
JavaScript实现的级联算法示例【省市二级联动功能】
Dec 25 Javascript
Nuxt v-bind绑定img src不显示的解决
Dec 05 Javascript
JavaScript实现省份城市的三级联动
Feb 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制作的意见反馈表源码
2007/03/11 PHP
php递归函数中使用return的注意事项
2014/01/17 PHP
php更新修改excel中的内容实例代码
2014/02/26 PHP
PHP实现发送邮件的方法(基于简单邮件发送类)
2015/12/17 PHP
javascript this用法小结
2008/12/19 Javascript
jquery和javascript的区别(常用方法比较)
2013/07/04 Javascript
用RadioButten或CheckBox实现div的显示与隐藏
2013/09/21 Javascript
Nodejs学习笔记之入门篇
2015/04/16 NodeJs
JavaScript html5 canvas画布中删除一个块区域的方法
2016/01/26 Javascript
js实现的万能flv网页播放器代码
2016/04/30 Javascript
怎么限制input的text里输入的值只能是数字(正则、js)
2016/05/16 Javascript
Bootstrap模块dropdown实现下拉框响应
2016/05/22 Javascript
select隐藏选中值对应的id,显示其它id的简单实现方法
2016/08/25 Javascript
RequireJS简易绘图程序开发
2016/10/28 Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
2017/01/20 Javascript
微信小程序实现登录页云层漂浮的动画效果
2017/05/05 Javascript
详解关于webpack多入口热加载很慢的原因
2019/04/24 Javascript
详解Node.js异步处理的各种写法
2019/06/09 Javascript
微信小程序如何访问公众号文章
2019/07/08 Javascript
vue路由教程之静态路由
2019/09/03 Javascript
JS使用正则表达式判断输入框失去焦点事件
2019/10/16 Javascript
零基础写python爬虫之爬虫的定义及URL构成
2014/11/04 Python
python创建进程fork用法
2015/06/04 Python
Python爬取京东的商品分类与链接
2016/08/26 Python
Python实现购物程序思路及代码
2017/07/24 Python
python3写爬取B站视频弹幕功能
2017/12/22 Python
Python常见字典内建函数用法示例
2018/05/14 Python
python实现统计代码行数的小工具
2019/09/19 Python
Django vue前后端分离整合过程解析
2020/11/20 Python
戴尔荷兰官方网站:Dell荷兰
2020/10/04 全球购物
中科软笔试题和面试题
2014/10/07 面试题
投标人廉洁自律承诺书
2014/05/26 职场文书
高中生综合素质自我评价
2015/03/06 职场文书
MySQL命令行操作时的编码问题详解
2021/04/14 MySQL
HTML+css盒子模型案例(圆,半圆等)“border-radius” 简单易上手
2021/05/10 HTML / CSS
浅谈MySQL之select优化方案
2021/08/07 MySQL