addEventListener('scroll') 使用 useRef 可滚动 <div /> - React
addEventListener('scroll') to scrollable <div /> using useRef - React
这是我第一次真正在项目中正确使用 React Hooks,所以如果我不太了解,请多多包涵。
在下面的组件中,我的目标是在加载时和滚动 div(不是 window)滚动时显示 <HelperTooltip>
我想在它滚动后隐藏 X像素数量。
我的想法是在滚动的 <div/>
元素上创建一个 useRef 对象,然后我可以添加一个带有回调函数的事件监听,然后可以切换状态以隐藏 <HelperTooltip>
我在下面创建了一个 Codesandbox 来尝试演示我正在尝试做的事情。正如您在演示中看到的那样,node.addEventListener('click')
工作正常,但是当我尝试调用 node.addEventListener('scroll')
时,它没有触发。
我不确定我是否采取了错误的方法,任何帮助将不胜感激。在 codesandbox 演示中,它是我试图在滚动时隐藏的反应图像,而不是 <HelperTooltip>
代码沙盒link:https://codesandbox.io/s/zxj322ln24
import React, { useRef, useCallback, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const App = props => {
const [isLogoActive, toggleLogo] = useState(true);
const scrollElementRef = useCallback(node => {
node.addEventListener("click", event => {
console.log("clicked", event);
});
/*
I want to add the scroll event listener
here and the set the state isLogoActive to
false like the event listener above but the 'scroll' event
is firing --- see below on line 21
*/
// node.addEventListener("scroll", event => {
// console.log("scrolled", event);
// toggle log
// });
});
return (
<div className="scrolling-container">
<div ref={scrollElementRef} className="scrolling-element">
<p>top</p>
{isLogoActive && (
<div className="element-to-hide-after-scroll">
<img
style={{ width: "100px", height: "100px" }}
src="https://arcweb.co/wp-content/uploads/2016/10/react-logo-1000-transparent-768x768.png"
/>
</div>
)}
<p>bottom</p>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("app"));
在您的示例中,滚动不是在 scrolling-element
上触发的,而是在 scrolling-container
上触发的,所以这就是您要放置 ref 的位置:https://codesandbox.io/s/ko4vm93moo :)
但正如 Throlle 所说,您也可以使用 onScroll 属性!
针对此特定用例的更简单方法可能是使用 onScroll
道具并使用事件 target
中的 scrollTop
属性 来确定您是否是否应该隐藏图像。
例子
const { useState } = React;
const App = props => {
const [isLogoActive, setLogoActive] = useState(true);
const onScroll = e => {
setLogoActive(e.target.scrollTop < 100);
};
return (
<div onScroll={onScroll} style={{ height: 300, overflowY: "scroll" }}>
<p style={{ marginBottom: 200 }}>top</p>
<img
style={{
width: 100,
height: 100,
visibility: isLogoActive ? "visible" : "hidden"
}}
src="https://arcweb.co/wp-content/uploads/2016/10/react-logo-1000-transparent-768x768.png"
/>
<p style={{ marginTop: 200 }}>bottom</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
这是使用 useRef()
在 div 上绑定 addEventListener 的正确方法
import React, { useState, useEffect, useCallback, useRef } from 'react';
function ScrollingWrapper(props) {
const [hasScrolledDiv, setScrolled] = useState(false);
const scrollContainer = useRef(null);
const onScroll = useCallback((event) => {
if(event.target.scrollTop > 125){
setScrolled(true);
} else if(event.target.scrollTop < 125) {
setScrolled(false);
}
}, []);
useEffect(() => {
scrollContainerWrapper.current.addEventListener('scroll', onScroll);
return () => scrollContainerWrapper.current.removeEventListener('scroll', onScroll);
},[]);
return (
<div ref={scrollContainerWrapper}>
{props.children}
</div>
);
}
export default ScrollingWrapper;
根据您的用例,节流 滚动事件侦听器通常也很好,因此它们不会 运行 每次像素更改。
const App = props => {
const [isLogoActive, setLogoActive] = useState(true);
const onScroll = useMemo(() => {
const throttled = throttle(e => setLogoActive(e.target.scrollTop < 100), 300);
return e => {
e.persist();
return throttled(e);
};
}, []);
return (
<div onScroll={onScroll}>
<img
style={{ visibility: isLogoActive ? 'visible' : 'hidden' }}
src="https://arcweb.co/wp-content/uploads/2016/10/react-logo-1000-transparent-768x768.png"
/>
</div>
);
};
throttle
函数在 lodash 中可用。
这是我第一次真正在项目中正确使用 React Hooks,所以如果我不太了解,请多多包涵。
在下面的组件中,我的目标是在加载时和滚动 div(不是 window)滚动时显示 <HelperTooltip>
我想在它滚动后隐藏 X像素数量。
我的想法是在滚动的 <div/>
元素上创建一个 useRef 对象,然后我可以添加一个带有回调函数的事件监听,然后可以切换状态以隐藏 <HelperTooltip>
我在下面创建了一个 Codesandbox 来尝试演示我正在尝试做的事情。正如您在演示中看到的那样,node.addEventListener('click')
工作正常,但是当我尝试调用 node.addEventListener('scroll')
时,它没有触发。
我不确定我是否采取了错误的方法,任何帮助将不胜感激。在 codesandbox 演示中,它是我试图在滚动时隐藏的反应图像,而不是 <HelperTooltip>
代码沙盒link:https://codesandbox.io/s/zxj322ln24
import React, { useRef, useCallback, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const App = props => {
const [isLogoActive, toggleLogo] = useState(true);
const scrollElementRef = useCallback(node => {
node.addEventListener("click", event => {
console.log("clicked", event);
});
/*
I want to add the scroll event listener
here and the set the state isLogoActive to
false like the event listener above but the 'scroll' event
is firing --- see below on line 21
*/
// node.addEventListener("scroll", event => {
// console.log("scrolled", event);
// toggle log
// });
});
return (
<div className="scrolling-container">
<div ref={scrollElementRef} className="scrolling-element">
<p>top</p>
{isLogoActive && (
<div className="element-to-hide-after-scroll">
<img
style={{ width: "100px", height: "100px" }}
src="https://arcweb.co/wp-content/uploads/2016/10/react-logo-1000-transparent-768x768.png"
/>
</div>
)}
<p>bottom</p>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("app"));
在您的示例中,滚动不是在 scrolling-element
上触发的,而是在 scrolling-container
上触发的,所以这就是您要放置 ref 的位置:https://codesandbox.io/s/ko4vm93moo :)
但正如 Throlle 所说,您也可以使用 onScroll 属性!
针对此特定用例的更简单方法可能是使用 onScroll
道具并使用事件 target
中的 scrollTop
属性 来确定您是否是否应该隐藏图像。
例子
const { useState } = React;
const App = props => {
const [isLogoActive, setLogoActive] = useState(true);
const onScroll = e => {
setLogoActive(e.target.scrollTop < 100);
};
return (
<div onScroll={onScroll} style={{ height: 300, overflowY: "scroll" }}>
<p style={{ marginBottom: 200 }}>top</p>
<img
style={{
width: 100,
height: 100,
visibility: isLogoActive ? "visible" : "hidden"
}}
src="https://arcweb.co/wp-content/uploads/2016/10/react-logo-1000-transparent-768x768.png"
/>
<p style={{ marginTop: 200 }}>bottom</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
这是使用 useRef()
在 div 上绑定 addEventListener 的正确方法import React, { useState, useEffect, useCallback, useRef } from 'react';
function ScrollingWrapper(props) {
const [hasScrolledDiv, setScrolled] = useState(false);
const scrollContainer = useRef(null);
const onScroll = useCallback((event) => {
if(event.target.scrollTop > 125){
setScrolled(true);
} else if(event.target.scrollTop < 125) {
setScrolled(false);
}
}, []);
useEffect(() => {
scrollContainerWrapper.current.addEventListener('scroll', onScroll);
return () => scrollContainerWrapper.current.removeEventListener('scroll', onScroll);
},[]);
return (
<div ref={scrollContainerWrapper}>
{props.children}
</div>
);
}
export default ScrollingWrapper;
根据您的用例,节流 滚动事件侦听器通常也很好,因此它们不会 运行 每次像素更改。
const App = props => {
const [isLogoActive, setLogoActive] = useState(true);
const onScroll = useMemo(() => {
const throttled = throttle(e => setLogoActive(e.target.scrollTop < 100), 300);
return e => {
e.persist();
return throttled(e);
};
}, []);
return (
<div onScroll={onScroll}>
<img
style={{ visibility: isLogoActive ? 'visible' : 'hidden' }}
src="https://arcweb.co/wp-content/uploads/2016/10/react-logo-1000-transparent-768x768.png"
/>
</div>
);
};
throttle
函数在 lodash 中可用。