ElementUI 官网 InfiniteScroll 使用:https://element.eleme.cn/#/zh-CN/component/infiniteScroll

首先先叙述一下需求,说明文章总体内容:

需求: 页面滚动到底部,触发接口数据加载,实现下滑无限滚动效果。


InfiniteScroll 问题总结

  • Vue 项目使用 InfiniteScroll 无限滚动组件
  • JS 实现无限滚动效果
    • 问题一:判断页面滑轮到底部的方式
    • 问题二:如果没有超过页面/盒子高度,导致没出现滑轮怎么办

Vue 项目使用 InfiniteScroll 无限滚动组件

首先为了更好的说明问题,和后续的解决方案,先说一下 ElementUI 组件的使用情况。整体的使用参照官方文档即可,使用还是很简单的,关键代码概览:

(1)首先是 Vue 部分:

<template>
<div class="main-iframe" v-infinite-scroll="load"> // 内容
</div>
</template>
<script>export default { methods: {load () {// 调用接口} }
}</script>

(2)如果要实现无限滚动的,最关键点是要有以下 CSS:

.main-iframe {height: calc(100vh);overflow: auto;// 其他CSS....
}

也就是 heightoverflow:auto。换句话说就是,在一个页面中存在一个给定高度 height 的盒子(无论 height 有多高),当给定 overflow:auto 的时候,就会在数据超过盒子本身高度 height 的时候,出现一个滚滑轮。此时 ElementUI 无限加载组件就会判断这个滚滑轮,当它滑动到这个盒子的底部的时候,触发 load 方法。本质就是下图这样的效果。

那假设这个页面,就只有这个盒子,那 height 设置成 calc(100vh) 占据视口100% ,就可以达到好像滑轮到了整个页面的底部实现加载的效果。当然如果该页面还有其他内容,那 height 做出相应调整即可。因此它的核心是到了这个盒子的底部。

随后在这个第一版的实现方式下,如果要回到顶部,那就是让这个盒子的滑轮回到顶部。

document.getElementsByClassName('main-iframe')[0].scrollTo({top: document.getElementById('content').offsetTop,behavior: 'smooth'
});

而目前虽然确实已经实现了功能,但到了具体的使用中发现,部分浏览器存在滚动失效的情况(滚动了几次后,就无法再次滚动),但不确定哪些浏览器会失效或者失效的原因,但大致可推断为浏览器兼容性问题,或者受到了相同浏览器不同版本的影响。

如果您依然要使用 ElementUI 组件的话,为了避免大篇幅引用,您可以前往该文章参考:

无限滚动 仅触发1次或几次 无效 可行 解决方案

如果还是会出现问题的话,那就不妨试试接下来的方案,不再使用 ElementUI 的滚动组件,而是直接使用 JS 手写这样的功能,笔者目前测试没问题,兼容性问题也只存在于太过老旧的浏览器上。


JS 实现无限滚动效果

首先如果要手动实现滚动效果,那肯定要监听滚动条事件。在 Vue 中,其实有两种选择,一种是监听 window 滚动条事件,另一种是监听某个具体元素的 @scroll 滚动条事件。但因为笔者目前需求的页面,只有这个需要监听滚动的元素,所以使用第一种方式。

而第二种方式因为笔者没有具体去实现,所以在这里没有相关实现代码,各位有需要可以参考下列方案去尝试。

监听事件:

mounted() {window.addEventListener('scroll', this.handleScroll);
},
beforeDestroy() {window.removeEventListener('scroll', this.handleScroll);
},

而如果要实现第一种方式,那就代表着要监听整个页面的滚动条,换句话说,滚动时新增的数据,要撑起整个页面的 height,不要让这个盒子的高度固定。再具体来说,就是从 CSS 入手:

.main-iframe {min-height: calc(100vh);// 其他CSS...
}

也就是 min-height 。换句话说就是整个盒子的最小高度是视口100%,当整个页面的滚动滑轮到了底部,就去调用接口,并添加数据给这个盒子。随后这个盒子的高度和页面的高度就会同步撑起。本质就是下图这样的效果。一定要注意,当前情况和使用 ElementUI 无限滚动组件时有本质区别。

而如果要实现第二种 @scroll 方式的话,CSS 依然至少是 height + overflow:auto。

第一种方式具体实现的 JS 就是:

handleScroll() {// 滚动条在Y轴上的滚动距离let scrollTop = 0; let bodyScrollTop = 0; let documentScrollTop = 0;if (document.body) {bodyScrollTop = document.body.scrollTop;}if (document.documentElement) {documentScrollTop = document.documentElement.scrollTop;}scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;// 浏览器视口的高度let windowHeight = 0;if (document.compatMode === 'CSS1Compat') {windowHeight = document.documentElement.clientHeight;} else {windowHeight = document.body.clientHeight;}// 文档的总高度let scrollHeight = 0; let bodyScrollHeight = 0; let documentScrollHeight = 0;if (document.body) {bodyScrollHeight = document.body.scrollHeight;}if (document.documentElement) {documentScrollHeight = document.documentElement.scrollHeight;}scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;if (scrollTop + windowHeight > scrollHeight - 50) {this.load(); // 调用接口}
}

而相对的,如果是第二种 @scroll 的方式,那就肯定不是像上面这样拿 window 相关的高度。而是需要去拿到:滚动条在当前元素上的滚动距离、该元素的固定高度、该元素的总高度。

此时回到顶部的功能,因为和最开始滑轮的情况不同,所以回到顶部功能需要重新写,简单来说就是要让 window 的滑轮回到顶部(这里参考 ElementUI 回到顶部的源码,手写了一个回到顶部的效果):

toTop() {let bodyScrollTop = 0;let documentScrollTop = 0;if (document.body) {bodyScrollTop = document.body.scrollTop;}if (document.documentElement) {documentScrollTop = document.documentElement.scrollTop;}let s = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;let step = 0;const interval = setInterval(() => {if (s <= 0) {clearInterval(interval);return;}step += 10;s -= step;window.scrollTo(0, s);}, 20);
}

到这里为止的参考文章:

判断滚动条是否到了底部

vue监听页面滚动事件


而使用第一种方式后,目前又遇到了两个坑。相关问题和解决方案如下。


问题一:判断页面滑轮到底部的方式

第一个问题是:判断页面滑轮到底部的方式。判断依据理论上是:

scrollTop + windowHeight === scrollHeight

也就是

滚动条在Y轴上滚动的距离 + 浏览器视口的高度 === 页面总高度

但是这么做之后,发现在部分浏览器中依然是失效的。不过失效原因通过 console.log 输出这三个值,很快就能定位到问题。问题就是,这个等式不可能完全成立,在实际不同浏览器的测试中发现,到达底部时,可能会出现: scrollTop + windowHeight < scrollHeight ,而这个差值在小数级别。

所以,为了解决这个问题,在上面的代码中,我设置了一个 50 的阈值,也就是:

scrollTop + windowHeight > scrollHeight - 50

这么设置之后,问题基本迎刃而解(当然这个阈值可以自己随意设定)。


问题二:如果没有超过页面/盒子高度,导致没出现滑轮怎么办

第二个问题是:如果首屏数据没有超过页面 / 盒子高度,导致该部分没出现滑轮怎么办。

因为现在是出现滑轮后,滚动滑轮才会调用 handleScroll(),然后进行一系列的判断。

其实解决方案也足够简单,代码就不展示了。解决方案其实有两种:

第一种:因为无限滚动组件在实现时,我们底部可能增加了一个 “下滑加载更多” 或 “已经滑到底部” 的提示语,那我们可以在没出现滚轮的时候,调整提示语,让使用者点击什么按钮,从而手动加载数据。但是这种方式感觉还是不太好。(判断何时没出现滚轮,在下面第二种方法上有写)

第二种是目前我使用的办法,说一下思路:当首屏接口调用完成时,手动调用一下 handleScroll,如果 scrollTop + windowHeight === scrollHeight (经过测试,就算是不同浏览器,如果数据量不够多,导致没能出现页面滑轮,这个等式也会在此时成立。当然如果此式真的不相等,也可以根据不同浏览器不相等的情况,给出一个合理的阈值,再去判断),那就意味着此时页面没出现滑轮,那就需要继续调用接口,直到页面出现滑轮。出现滑轮后,这个等式就肯定不会成立,此时跳出循环,不再调用接口即可。

【ElementUI】InfiniteScroll 无限滚动组件在部分浏览器中滚动失效 的 解决方案相关推荐

  1. java 滚动截屏_浏览器实现滚动截屏

    工作日志:实现浏览器滚动截屏,并且是指定的iframe在跨域的情况下. 首先拿到这个需求的时候,想了一下,实现滚动截屏并不难,难的具体的情况如下, 在IE浏览器的情况下,在前端实现,并且iframe是 ...

  2. html+监听+页面滚动到底部,解决HTML5中滚动到底部的事件问题

    问题:在H5中,我们有这样的需求:例如有列表的时候,滚动到底部时,需要加载更多. 解决方案:可以采用window的滚动事件进行处理 分析:如果滚动是针对整个屏幕而言的(不针对于某个界面小块),那么这个 ...

  3. Java Web项目中HTML文件中的汉字在浏览器中显示乱码的解决方案

    今天在做一个Java Web项目的时候,html中的汉字在浏览器中显示为乱码,分析其可能原因有: (1)html文件属性中有默认的编码方式,如果它的设置与html文档中content charset属 ...

  4. elementUI InfiniteScroll 无限滚动 一次加载到底不受禁用限制问题解决

    解决方法: 删除官方样例中的style="overflow:auto" ElementUI的官方样例 <div class="infinite-list-wrapp ...

  5. 谷歌Chrom浏览器中自动翻译问题的解决方案

    对于经常要阅读国外文献的人来说,谷歌自带的翻译网页功能简直不要太方便. 但是有的时候谷歌自带的翻译网页功能有些隐蔽,如果没有找到可以按照以下步骤进行排查. step1:点击Chrom浏览器的设置 st ...

  6. html 无组件上传图片,无组件上传图片到数据库中,最完整解决方案

    ::::::: 此程序属扬子原创 :::::::::::::::::: :::::: 在sql2000,2000s中测试通过:::::::: :::::::联系我:qq:21112856,email: ...

  7. 各浏览器中的鼠标滚轮事件处理

    滚轮事件是不同浏览器会有一点点区别,一个像Firefox使用DOMMouseScroll ,ff也可以使用addEventListener方法绑定DomMouseScroll事件,其他的浏览器滚轮事件 ...

  8. 在浏览器中执行Kettle job或者transformation

    通过URL执行Kettle的转换或者任务,这个功能可以Kettle的web service.假如有这样的一种情形:第三方想从你这里读取数据,然而,你又不要写web service代码.任何人都可以从w ...

  9. 使用Element的 InfiniteScroll 无限滚动组件报错

    一.问题描述 在使用Element的InfiniteScroll 无限滚动时候出现以下错误: TypeError: Failed to execute 'observe' on 'MutationOb ...

最新文章

  1. select, epoll的个人总结
  2. 排序方法的分类 算法
  3. c高级语言程序设计B试题,2019-2010-2-《高级语言程序设计(C)》期末考试-题
  4. Oracle入门(十五)之数据库锁
  5. php 中英文截取 php,PHP 中英文截取无乱码
  6. Scrapy开发指南
  7. django+xadmin在线教育平台慕学网(一)
  8. 树莓派:Adafruit的I2C SSD1306 OLED驱动
  9. Word巧用大纲视图 快速重排版面
  10. Go 依赖管理工具 Dep 的安装及配置
  11. MOOC《程序设计入门——C语言》翁恺 第六周编程练习及答案
  12. windows10复制粘贴键突然失效 的一个最简单的解决方法
  13. 路由器修改wifi密码
  14. 第一讲:双活容灾技术和方案概述
  15. linux 批量替换文件cp,Linux下批量修改文件名
  16. MySQL中的表中增加删除字段
  17. 2021年的最后一天
  18. 10个python接私活的平台,整整10个,总有适合你的,你有技术就有钱
  19. meb备份mysql,MySQL企业版备份工具MEB
  20. js-字符串隐藏部分文字,如车牌号脱敏

热门文章

  1. 给你的应用设置系统签名
  2. PyQt5 - 获取鼠标坐标并且绘制点
  3. 编程将一个二维数组元素变换为逆向存放,即按元素在内存中的物理排列位置,第一个元素变成倒数第一个元素,第二个元素变成倒数第二个元素,依此类推。
  4. select2如何设置默认空值
  5. 简易新年倒计时的js部分
  6. 软件项目上线完整流程
  7. Python-Numpy中Array用法总结
  8. 智过网:一级建造师证书可以同时注册的证书!
  9. win7 与 ubuntu双系统 ubuntu系统无法启动问题
  10. 新传专业需要计算机二级吗,大学生有必要去考取计算机二级证书吗?