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 相关文章推荐
脚本收藏iframe
Jul 21 Javascript
jQuery 改变CSS样式基础代码
Feb 11 Javascript
JS去除数组重复值的五种不同方法
Sep 06 Javascript
JavaScript onkeydown事件入门实例(键盘某个按键被按下)
Oct 17 Javascript
JS实现同一个网页布局滑动门和TAB选项卡实例
Sep 23 Javascript
逐一介绍Jquery data()、Jquery stop()、jquery delay()函数(详)
Nov 04 Javascript
javascript瀑布流布局实现方法详解
Feb 17 Javascript
JS实现环形进度条(从0到100%)效果
Jul 05 Javascript
js html5 css俄罗斯方块游戏再现
Oct 17 Javascript
vue监听input标签的value值方法
Aug 27 Javascript
基于layui实现高级搜索(筛选)功能
Jul 26 Javascript
JavaScript中交换值的10种方法总结
Aug 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
php 搜索框提示(自动完成)实例代码
2012/02/05 PHP
php中使用base HTTP验证的方法
2015/04/20 PHP
php生成年月日下载列表的方法
2015/04/24 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
PHP+iframe图片上传实现即时刷新效果
2016/11/18 PHP
php简单生成一组与多组随机字符串的方法
2017/05/09 PHP
PHP实现SMTP邮件的发送实例
2018/09/27 PHP
PHP goto语句用法实例
2019/08/06 PHP
改进:论坛UBB代码自动插入方式
2006/12/22 Javascript
Prototype使用指南之ajax
2007/01/10 Javascript
JavaScript中的isXX系列是否继续使用的分析
2011/04/16 Javascript
JavaScript学习笔记之JS对象
2015/01/22 Javascript
jQuery()方法的第二个参数详解
2015/04/29 Javascript
jQuery中(function($){})(jQuery)详解
2015/07/15 Javascript
使用JQuery实现的分页插件分享
2015/11/05 Javascript
js基本算法:冒泡排序,二分查找的简单实例
2016/10/08 Javascript
node.js入门学习之url模块
2017/02/25 Javascript
JS中使用 after 伪类清除浮动实例
2017/03/01 Javascript
使用wxapp-img-loader自定义组件实现微信小程序图片预加载功能
2018/10/18 Javascript
vue权限问题的完美解决方案
2019/05/08 Javascript
微信小程序上传文件到阿里OSS教程
2019/05/20 Javascript
js实现select下拉框选择
2020/01/11 Javascript
[03:51]吞吞映像 每周精彩击杀top10第二弹
2014/06/25 DOTA
[01:51]2018年度CS GO最具人气外援-完美盛典
2018/12/16 DOTA
高效使用Python字典的清单
2018/04/04 Python
Django的性能优化实现解析
2019/07/30 Python
selenium+python实现基本自动化测试的示例代码
2021/01/27 Python
全球速卖通巴西站点:Aliexpress巴西
2016/08/24 全球购物
写给老婆的检讨书
2014/02/21 职场文书
2014年社区学雷锋活动总结
2014/03/09 职场文书
安全生产目标责任书
2014/04/14 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
大学三好学生主要事迹范文
2015/11/03 职场文书
高一数学教学反思
2016/02/18 职场文书
如何用python反转图片,视频
2021/04/24 Python
JVM之方法返回地址详解
2022/02/28 Java/Android