![](/img/trans.png)
[英]Detecting weather user scrolls the bottom of the div or not in react js and javascript
[英]Detecting when user scrolls to bottom of div with React js
我有一个包含不同部分的网站。 我正在使用 segment.io 来跟踪页面上的不同操作。 如何检测用户是否滚动到 div 的底部? 我尝试了以下操作,但它似乎是在我滚动页面时触发的,而不是当我到达 div 底部时触发的。
componentDidMount() {
document.addEventListener('scroll', this.trackScrolling);
}
trackScrolling = () => {
const wrappedElement = document.getElementById('header');
if (wrappedElement.scrollHeight - wrappedElement.scrollTop === wrappedElement.clientHeight) {
console.log('header bottom reached');
document.removeEventListener('scroll', this.trackScrolling);
}
};
一个更简单的方法是使用scrollHeight 、 scrollTop和clientHeight 。
从总可滚动高度中减去滚动高度。 如果这等于可见区域,则您已到达底部!
element.scrollHeight - element.scrollTop === element.clientHeight
在 React 中,只需为可滚动元素添加一个 onScroll 侦听器,并在回调中使用event.target
。
class Scrollable extends Component {
handleScroll = (e) => {
const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
if (bottom) { ... }
}
render() {
return (
<ScrollableElement onScroll={this.handleScroll}>
<OverflowingContent />
</ScrollableElement>
);
}
}
我发现这更直观,因为它处理可滚动元素本身,而不是window
,并且它遵循正常的 React 做事方式(不使用 id,忽略 DOM 节点)。
您还可以操纵方程式以在页面上方触发(例如,延迟加载内容/无限滚动)。
您可以使用el.getBoundingClientRect().bottom
来检查底部是否已被查看
isBottom(el) {
return el.getBoundingClientRect().bottom <= window.innerHeight;
}
componentDidMount() {
document.addEventListener('scroll', this.trackScrolling);
}
componentWillUnmount() {
document.removeEventListener('scroll', this.trackScrolling);
}
trackScrolling = () => {
const wrappedElement = document.getElementById('header');
if (this.isBottom(wrappedElement)) {
console.log('header bottom reached');
document.removeEventListener('scroll', this.trackScrolling);
}
};
我们还可以使用 ref 检测 div 的滚动结束。
import React, { Component } from 'react';
import {withRouter} from 'react-router-dom';
import styles from 'style.scss';
class Gallery extends Component{
paneDidMount = (node) => {
if(node) {
node.addEventListener("scroll", this.handleScroll.bind(this));
}
}
handleScroll = (event) => {
var node = event.target;
const bottom = node.scrollHeight - node.scrollTop === node.clientHeight;
if (bottom) {
console.log("BOTTOM REACHED:",bottom);
}
}
render() {
var that = this;
return(<div className={styles.gallery}>
<div ref={that.paneDidMount} className={styles.galleryContainer}>
...
</div>
</div>);
}
}
export default withRouter(Gallery);
这是使用 React Hooks 和 ES6 的解决方案:
import React, { useRef, useEffect } from 'react';
const MyListComponent = () => {
const listInnerRef = useRef();
const onScroll = () => {
if (listInnerRef.current) {
const { scrollTop, scrollHeight, clientHeight } = listInnerRef.current;
if (scrollTop + clientHeight === scrollHeight) {
// TO SOMETHING HERE
console.log('Reached bottom')
}
}
};
return (
<div className="list">
<div className="list-inner" onScroll={() => onScroll()} ref={listInnerRef}>
{/* List items */}
</div>
</div>
);
};
export default List;
扩展 chandresh 的答案以使用 react hooks 和 ref 我会这样做;
import React, {useState, useEffect} from 'react';
export default function Scrollable() {
const [referenceNode, setReferenceNode] = useState();
const [listItems] = useState(Array.from(Array(30).keys(), (n) => n + 1));
useEffect(() => {
return () => referenceNode.removeEventListener('scroll', handleScroll);
}, []);
function handleScroll(event) {
var node = event.target;
const bottom = node.scrollHeight - node.scrollTop === node.clientHeight;
if (bottom) {
console.log('BOTTOM REACHED:', bottom);
}
}
const paneDidMount = (node) => {
if (node) {
node.addEventListener('scroll', handleScroll);
setReferenceNode(node);
}
};
return (
<div
ref={paneDidMount}
style={{overflowY: 'scroll', maxHeight: '400px'}}
>
<ul>
{listItems.map((listItem) => <li>List Item {listItem}</li>)}
</ul>
</div>
);
}
这个答案属于 Brendan,让我们让它发挥作用
export default () => {
const handleScroll = (e) => {
const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
if (bottom) {
console.log("bottom")
}
}
return (
<div onScroll={handleScroll} style={{overflowY: 'scroll', maxHeight: '400px'}} >
//overflowing elements here
</div>
)
}
如果第一个 div 不可滚动,它将不起作用,并且 onScroll 在第一个 div 之后的 div 等子元素中对我不起作用,因此 onScroll 应该位于第一个溢出的 HTML 标记处
在你的 React.Component 中添加以下函数,你就完成了:]
componentDidMount() {
window.addEventListener("scroll", this.onScroll, false);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.onScroll, false);
}
onScroll = () => {
if (this.hasReachedBottom()) {
this.props.onScrollToBottom();
}
};
hasReachedBottom() {
return (
document.body.offsetHeight + document.body.scrollTop ===
document.body.scrollHeight
);
}
我知道这已经得到了回答,但我认为另一个好的解决方案是使用开源社区中已有的内容而不是 DIY。 React Waypoints是一个为解决这个问题而存在的库。 (虽然不要问我为什么这个确定一个人是否滚动通过 HTML 元素的问题空间被称为“航点”,哈哈)
我认为它的道具合同设计得很好,绝对鼓励你去看看。
我在我的代码中使用了
.modify-table-wrap { padding-top: 50px; height: 100%; overflow-y: scroll; }
并在目标js中添加代码
handleScroll = (event) => {
const { limit, offset } = this.state
const target = event.target
if (target.scrollHeight - target.scrollTop === target.clientHeight) {
this.setState({ offset: offset + limit }, this.fetchAPI)
}
}
return (
<div className="modify-table-wrap" onScroll={this.handleScroll}>
...
<div>
)
为了评估我的浏览器是否已滚动到 div 的底部,我采用了以下解决方案:
const el = document.querySelector('.your-element');
const atBottom = Math.ceil(el.scrollTop + el.offsetHeight) === el.scrollHeight;
在滚动 div 后放置一个高度为 0 的 div。 然后使用这个自定义钩子来检测这个 div 是否可见。
const bottomRef = useRef();
const reachedBottom = useCustomHooks(bottomRef);
return(
<div>
{search resault}
</div>
<div ref={bottomRef}/> )
如果到达底部, reachedBottom
将切换为true
下面的解决方案在大多数浏览器上工作正常,但其中一些有问题。
element.scrollHeight - element.scrollTop === element.clientHeight
更好和最准确的方法是使用下面适用于所有浏览器的代码。
Math.abs(e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop) < 1
所以最终的代码应该是这样的
const App = () => {
const handleScroll = (e) => {
const bottom = Math.abs(e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop) < 1;
if (bottom) { ... }
}
return(
<div onScroll={handleScroll}>
...
</div>
)
}
这个答案属于布伦丹,但我能够以这种方式使用该代码。
window.addEventListener("scroll", (e) => {
const bottom =
e.target.scrollingElement.scrollHeight -
e.target.scrollingElement.scrollTop ===
e.target.scrollingElement.clientHeight;
console.log(e);
console.log(bottom);
if (bottom) {
console.log("Reached bottom");
}
});
而其他人可以通过
e.target.scrollHeight
直接访问目标内部,
我可以通过e.target.scrollingElement.scrollHeight
实现同样的目标
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.