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 相关文章推荐
屏蔽鼠标右键、Ctrl+n、shift+F10、F5刷新、退格键 的javascript代码
Apr 01 Javascript
地震发生中逃生十大法则
May 12 Javascript
javascript 写类方式之四
Jul 05 Javascript
js中设置元素class的三种方法小结
Aug 28 Javascript
IE中jquery.form中ajax提交没反应解决方法分享
Sep 11 Javascript
jquery实现输入框动态增减的实例代码
Jul 14 Javascript
基于JavaScript实现添加到购物车效果附源码下载
Aug 22 Javascript
jQuery文本框得到与失去焦点动态改变样式效果
Sep 08 Javascript
React router动态加载组件之适配器模式的应用详解
Sep 12 Javascript
小程序关于请求同步的总结
May 05 Javascript
微信小程序云开发之云函数详解
May 16 Javascript
浅谈vue 二级路由嵌套和二级路由高亮问题
Aug 06 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
SONY SRF-22W(33W)的电路分析和维修案例
2021/03/02 无线电
PHP 利用Mail_MimeDecode类提取邮件信息示例
2014/01/26 PHP
利用“多说”制作留言板、评论系统
2015/07/14 PHP
PHP常见错误提示含义解释(实用!值得收藏)
2016/04/25 PHP
Laravel框架之解决前端显示图片问题
2019/10/24 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
在第一个input框内输入内容.textarea自动得到第一个文件框的值的javascript代码
2007/04/20 Javascript
IE中createElement需要注意的一个问题
2010/07/13 Javascript
JavaScript 打地鼠游戏代码说明
2010/10/12 Javascript
jQuery的.live()和.die() 使用介绍
2011/09/10 Javascript
Javascript 判断是否存在函数的方法
2013/01/03 Javascript
tangram框架响应式加载图片方法
2013/11/21 Javascript
javascript 原型链维护和继承详解
2014/11/26 Javascript
Jquery 实现checkbox全选方法
2015/01/28 Javascript
JQuery中clone方法复制节点
2015/05/18 Javascript
JS实现网页标题栏显示当前时间和日期的完整代码
2015/11/02 Javascript
深入分析Javascript事件代理
2016/01/30 Javascript
在localStorage中存储对象数组并读取的方法
2016/09/24 Javascript
JavaScript条件判断_动力节点Java学院整理
2017/06/26 Javascript
在Vue.js中使用Mixins的方法
2017/09/12 Javascript
微信小程序 循环及嵌套循环的使用总结
2017/09/26 Javascript
基于 Vue 实现一个酷炫的 menu插件
2017/11/14 Javascript
浅谈js中的bind
2019/03/18 Javascript
Angular 多模块项目构建过程
2020/02/13 Javascript
Vue路由守卫及页面登录权限控制的设置方法(两种)
2020/03/31 Javascript
Vue 使用typescript如何优雅的调用swagger API
2020/09/01 Javascript
python实现随机调用一个浏览器打开网页
2018/04/21 Python
Python闭包思想与用法浅析
2018/12/27 Python
Python字符串split及rsplit方法原理详解
2020/06/29 Python
复古服装:RetroStage
2019/05/10 全球购物
俄罗斯厨房产品购物网站:COOK HOUSE
2021/03/15 全球购物
会计学个人自荐信模板
2013/12/13 职场文书
离婚协议书该怎么写
2014/10/04 职场文书
个人年终总结结尾
2015/03/06 职场文书
2015年度个人工作总结报告
2015/10/24 职场文书
浅谈Python中对象是如何被调用的
2022/04/06 Python