Javascript 使用 React js 检测用户何时滚动到 div 的底部
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45585542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detecting when user scrolls to bottom of div with React js
提问by ewwink
I have a website with different sections. I am using segment.io to track different actions on the page. How can I detect if a user has scrolled to the bottom of a div? I have tried the following but it seems to be triggered as soon as I scroll on the page and not when I reached the bottom of the div.
我有一个包含不同部分的网站。我正在使用 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);
}
};
回答by Brendan McGill
An even simpler way to do it is with scrollHeight, scrollTop, and clientHeight.
一个更简单的方法是使用scrollHeight、scrollTop和clientHeight。
Subtract the scrolled height from the total scrollable height. If this is equal to the visible area, you've reached the bottom!
从总可滚动高度中减去滚动高度。如果这等于可见区域,则您已到达底部!
element.scrollHeight - element.scrollTop === element.clientHeight
In react, just add an onScroll listener to the scrollable element, and use event.targetin the callback.
在 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>
);
}
}
I found this to be more intuitive because it deals with the scrollable element itself, not the window, and it follows the normal React way of doing things (not using ids, ignoring DOM nodes).
我发现这更直观,因为它处理可滚动元素本身,而不是window,并且它遵循正常的 React 做事方式(不使用 id,忽略 DOM 节点)。
You can also manipulate the equation to trigger higher up the page (lazy loading content/infinite scroll, for example).
您还可以操纵方程式以在页面上方触发(例如,延迟加载内容/无限滚动)。
回答by ewwink
you can use el.getBoundingClientRect().bottomto check if the bottom has been viewed
您可以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);
}
};
回答by Chandresh
We can also detect div's scroll end by using ref.
我们还可以使用 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);
回答by Danchez
I know this has already been answered but, I think another good solution is to use what's already available out in the open source community instead of DIY. React Waypointsis a library that exists to solve this very problem. (Though don't ask me why the this problem space of determining if a person scrolls past an HTML element is called "waypoints," haha)
我知道这已经得到了回答,但我认为另一个好的解决方案是使用开源社区中已有的内容而不是 DIY。React Waypoints是一个为解决这个问题而存在的库。(虽然不要问我为什么这个确定一个人是否滚动通过 HTML 元素的问题空间被称为“航点”,哈哈)
I think it's very well designed with its props contract and definitely encourage you to check it out.
我认为它的道具合同设计得很好,绝对鼓励你去看看。
回答by Allan Guwatudde
Extending chandresh's answer to use react hooks and ref I would do it like this;
扩展 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>
);
}
回答by Zahidur Rahman Faisal
Add following functions in your React.Component and you're done :]
在你的 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
);
}

