如何在React中监听document body并转换原生JS滚动交互代码?
React滚动交互逻辑补全方案
核心解决要点
- 用
useState替代全局变量管理激活状态,确保组件状态与渲染同步 - 通过
useEffect绑定/解绑document.body的mouseup事件,避免内存泄漏 - 用
useRef绑定.wrapper元素,替代原生document.querySelector操作DOM
完整实现代码
import { useState, useRef, useEffect } from 'react'; const ScrollComponent = () => { const scrollerRef = useRef(null); const wrapperRef = useRef(null); const [active, setActive] = useState(false); const handleMouseDown = () => { setActive("middle"); scrollerRef.current?.classList.add("scrolling"); }; const handleMouseUp = () => { setActive(false); scrollerRef.current?.classList.remove("scrolling"); }; // 滚动逻辑函数(根据你的需求实现具体滚动行为) const scrollIt = (scrollX) => { wrapperRef.current?.scrollTo({ left: scrollX, behavior: 'smooth' }); }; // 获取wrapper位置并触发滚动(可根据你的触发时机调整调用时机) const triggerScroll = () => { const wrapperLeft = wrapperRef.current?.getBoundingClientRect().left; if (wrapperLeft !== undefined) { scrollIt(wrapperLeft); } }; // 绑定body的mouseup事件 useEffect(() => { document.body.addEventListener('mouseup', handleMouseUp); // 组件卸载时移除监听 return () => { document.body.removeEventListener('mouseup', handleMouseUp); }; }, []); return ( <div className="wrapper" ref={wrapperRef}> <div className="middle"> <img src="images/vr-iootz.jpg" draggable="false" alt="VR场景图" /> </div> <div ref={scrollerRef} className="scroller scroller-middle" onMouseDown={handleMouseDown} > <svg className="scroller__thumb" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" > <polygon points="0 50 37 68 37 32 0 50" fill="rgb(24,24,62)" /> <polygon points="100 50 64 32 64 68 100 50" fill="rgb(24,24,62)" /> </svg> </div> </div> ); }; export default ScrollComponent;
关键细节说明
- 状态管理:用
useState维护active状态,替代全局变量,确保状态变化能触发组件正确渲染 - 事件监听:通过
useEffect在组件挂载时添加mouseup监听,卸载时自动移除,避免内存泄漏 - 安全DOM操作:使用可选链操作符
?.判断ref的current是否存在,防止空指针报错 - 元素绑定:给
.wrapper添加useRef,直接通过wrapperRef.current获取元素,符合React组件化DOM操作规范
内容的提问来源于stack exchange,提问作者Kiki-ko
相关产品推荐
相关产品推荐

