React 无法触发 window.onmouseup
React can't trigger window.onmouseup
我有一个滑块组件,它应该在鼠标抬起后停止移动。我浏览了论坛,我的代码与
非常相似
const Slider = ({ mainColour }) => {
const [cursorPos, setCursorPos] = React.useState(0);
const [isSliding, setSliding] = React.useState(false);
const ref = React.useRef();
const drag = e => {
console.log("dragging");
setCursorPos(e.pageY);
};
const startDrag = e => {
setSliding(true);
window.addEventListener("mousemove", drag);
window.addEventListener("mouseup", function() {
ref.current.onmousedown = null;
ref.current.onmouseup = null;
ref.current.onmousemove = null;
setSliding(false);
window.onmouseup = null;
});
};
return (
<div
className={`cursor ${isSliding ? "active" : ""}`}
ref={ref}
style={{
top: `${cursorPos}px`,
backgroundColor: `${mainColour}`
}}
onMouseDown={event => startDrag(event)}
></div>
);
};
export default Slider;
但是,当 startDrag 触发时,window.onmouseup 侦听器似乎没有工作并且不会停止滑块。对于为什么它不起作用的任何见解,我们将不胜感激。
https://codesandbox.io/s/lucid-sunset-8e78r
React 可以触发mouseup
,你只需要在mouseup
时为drag()
使用window.removeEventListener
。这就是为什么您在 mouseup
之后在控制台中看到 dragging
的原因,您只是忘记取消订阅该事件:)
window.onmouseup = null;
与 window.removeEventListener("mousemove")
不同。
const Slider = ({ mainColour }) => {
const [cursorPos, setCursorPos] = React.useState(0);
const [isSliding, setSliding] = React.useState(false);
const ref = React.useRef();
const drag = e => {
console.log("dragging");
setCursorPos(e.pageY);
};
useEffect(() => {
if (isSliding) {
window.addEventListener("mousemove", drag);
}
}, [isSliding]);
useEffect(() => {
window.addEventListener("mouseup", function() {
window.removeEventListener("mousemove", drag);
setSliding(false);
});
});
const startDrag = () => setSliding(true);
return (
<div
className={`cursor ${isSliding ? "active" : ""}`}
ref={ref}
style={{
top: `${cursorPos}px`,
backgroundColor: `${mainColour}`
}}
onMouseDown={event => startDrag(event)}
/>
);
};
我同意 artanik 的评论,但有非常细微的变化。我宁愿只在 isSliding 更改值时设置和取消设置它,而不是在没有任何依赖项的情况下使用 useEffect,并不断地从 window 对象中添加和删除事件侦听器。此外,似乎 ref 没有在任何地方使用,所以我假设你可以只为 ref.
中的元素设置它而不是使用 window 对象
用空数组触发一次 useEffect 的目的是为了不 运行 它每次渲染。想象一个组件会发生大量状态更改和数据通过它,不需要在每次渲染时一次性添加和删除一堆事件侦听器。
const Slider = ({ mainColour }) => {
const [cursorPos, setCursorPos] = React.useState(0);
const [isSliding, setSliding] = React.useState(false);
///only do this once, when the component mounts
useEffect(() => {
window.addEventListener("mousedown", startDrag);
window.addEventListener("mouseup", endDrag);
},[]);
//and setting and unseting the event as needed
useEffect(() => {
if (isSliding) {
window.onmousemove = handleDrag;
}
else{
window.onmousemove = null;
}
}, [isSliding]);
const startDrag = () => setSliding(true);
const endDrag = () => setSliding(false);
const handleDrag = (e) =>{
console.log("dragging");
setCursorPos(e.pageY);
}
return (
<div
className={`cursor ${isSliding ? "active" : ""}`}
style={{
top: `${cursorPos}px`,
backgroundColor: `${mainColour}`
}}
/>
);
};
我有一个滑块组件,它应该在鼠标抬起后停止移动。我浏览了论坛,我的代码与
const Slider = ({ mainColour }) => {
const [cursorPos, setCursorPos] = React.useState(0);
const [isSliding, setSliding] = React.useState(false);
const ref = React.useRef();
const drag = e => {
console.log("dragging");
setCursorPos(e.pageY);
};
const startDrag = e => {
setSliding(true);
window.addEventListener("mousemove", drag);
window.addEventListener("mouseup", function() {
ref.current.onmousedown = null;
ref.current.onmouseup = null;
ref.current.onmousemove = null;
setSliding(false);
window.onmouseup = null;
});
};
return (
<div
className={`cursor ${isSliding ? "active" : ""}`}
ref={ref}
style={{
top: `${cursorPos}px`,
backgroundColor: `${mainColour}`
}}
onMouseDown={event => startDrag(event)}
></div>
);
};
export default Slider;
但是,当 startDrag 触发时,window.onmouseup 侦听器似乎没有工作并且不会停止滑块。对于为什么它不起作用的任何见解,我们将不胜感激。
https://codesandbox.io/s/lucid-sunset-8e78r
React 可以触发mouseup
,你只需要在mouseup
时为drag()
使用window.removeEventListener
。这就是为什么您在 mouseup
之后在控制台中看到 dragging
的原因,您只是忘记取消订阅该事件:)
window.onmouseup = null;
与 window.removeEventListener("mousemove")
不同。
const Slider = ({ mainColour }) => {
const [cursorPos, setCursorPos] = React.useState(0);
const [isSliding, setSliding] = React.useState(false);
const ref = React.useRef();
const drag = e => {
console.log("dragging");
setCursorPos(e.pageY);
};
useEffect(() => {
if (isSliding) {
window.addEventListener("mousemove", drag);
}
}, [isSliding]);
useEffect(() => {
window.addEventListener("mouseup", function() {
window.removeEventListener("mousemove", drag);
setSliding(false);
});
});
const startDrag = () => setSliding(true);
return (
<div
className={`cursor ${isSliding ? "active" : ""}`}
ref={ref}
style={{
top: `${cursorPos}px`,
backgroundColor: `${mainColour}`
}}
onMouseDown={event => startDrag(event)}
/>
);
};
我同意 artanik 的评论,但有非常细微的变化。我宁愿只在 isSliding 更改值时设置和取消设置它,而不是在没有任何依赖项的情况下使用 useEffect,并不断地从 window 对象中添加和删除事件侦听器。此外,似乎 ref 没有在任何地方使用,所以我假设你可以只为 ref.
中的元素设置它而不是使用 window 对象用空数组触发一次 useEffect 的目的是为了不 运行 它每次渲染。想象一个组件会发生大量状态更改和数据通过它,不需要在每次渲染时一次性添加和删除一堆事件侦听器。
const Slider = ({ mainColour }) => {
const [cursorPos, setCursorPos] = React.useState(0);
const [isSliding, setSliding] = React.useState(false);
///only do this once, when the component mounts
useEffect(() => {
window.addEventListener("mousedown", startDrag);
window.addEventListener("mouseup", endDrag);
},[]);
//and setting and unseting the event as needed
useEffect(() => {
if (isSliding) {
window.onmousemove = handleDrag;
}
else{
window.onmousemove = null;
}
}, [isSliding]);
const startDrag = () => setSliding(true);
const endDrag = () => setSliding(false);
const handleDrag = (e) =>{
console.log("dragging");
setCursorPos(e.pageY);
}
return (
<div
className={`cursor ${isSliding ? "active" : ""}`}
style={{
top: `${cursorPos}px`,
backgroundColor: `${mainColour}`
}}
/>
);
};