React电商产品行向右滚动进度条开发:解决addEventListener为null报错
报错原因&修复方案
你现在遇到的报错本质是选择器写错导致拿不到对应DOM元素,加上多处混用DOM和组件实例方法,不符合React开发规范,以下是完整修复步骤和代码:
具体错误点
- 你用
document.querySelector("CDG")选择元素,querySelector里类名需要加.前缀,正确写法是.CDG,没加前缀就会返回null,调用addEventListener自然就报错了 - 不要直接用原生API操作DOM,React推荐用
ref获取DOM引用,避免渲染时序导致的拿不到元素问题 - 你把DOM元素当成了组件实例,调用
element.calculateScrollDistance()和element.setState()都是错的,setState是组件的方法,不是DOM的方法 - 组件卸载时没有移除滚动监听,会有内存泄漏风险
修复后完整代码
import React from 'react'; import { taskData } from "./cdg-data"; import ProgressBar from './progress'; class CDG extends React.Component { state = { scrollPosition: 0 } // 声明ref存储滚动容器的DOM引用 scrollRef = React.createRef(); calculateScrollDistance = () => { const element = this.scrollRef.current; if (!element) return; const pixels = element.scrollLeft; // 当前滚动的像素值 const elementWidth = element.clientWidth; // 容器可见宽度 const fullElementWidth = element.scrollWidth; // 容器总宽度(含滚动隐藏部分) const totalScrollableDistance = fullElementWidth - elementWidth; // 处理滚动到底部时分母为0的边界情况 const scrollPosition = totalScrollableDistance === 0 ? 0 : Math.floor(pixels / totalScrollableDistance * 100); this.setState({ scrollPosition, }) } listenToScrollEvent = () => { const element = this.scrollRef.current; if (!element) return; element.addEventListener("scroll", this.handleScroll); } handleScroll = () => { requestAnimationFrame(this.calculateScrollDistance); } componentDidMount() { this.listenToScrollEvent(); } componentWillUnmount() { // 组件卸载时移除监听,避免内存泄漏 const element = this.scrollRef.current; if (element) { element.removeEventListener("scroll", this.handleScroll); } } render() { return( <div> <h2 className="cdg-title">THE COLLECTION</h2> {/* 把ref绑定到滚动容器上 */} <div className="CDG" ref={this.scrollRef}> {taskData.map((item, index) => { // 给遍历的元素加key属性,避免React警告 return ( <div className="image-container" key={index}> <a href={item.url} target="_blank" rel="noreferrer"> <p className="title">{item.title}</p> <p className="price">{item.price}</p> </a> <img className="cdg-image" src={item.image} alt="Converse" /> </div> ); })} </div> <div className="Progress"> <ProgressBar scroll={this.state.scrollPosition + '%'}/> </div> </div> ); } } export default CDG;
额外说明
如果你的.CDG容器还没加滚动样式,记得补上css才能触发滚动事件:
.CDG { display: flex; overflow-x: auto; /* 其他你需要的宽高、间距样式 */ }
内容的提问来源于stack exchange,提问作者bex
相关产品推荐
相关产品推荐

