点击按钮后容器无法滚动?React横向滑块问题求助
问题:横向滑块点击圆点按钮无法触发滚动
我正在实现一个带按钮的横向滑块,包含6个卡片和6个点按钮。点击索引为1的第二个按钮时,应该滑动到第二张图片,但滚动事件完全没生效。
相关代码
CSS代码
@media only screen and (max-width: 810px){ .fake-magicwall ul{ overflow: hidden; overflow-x: auto; flex-wrap: nowrap; } .dot{ width: 15px; height: 15px; border-radius: 50%; margin: 10px; } }
React组件代码
import React from 'react' import './Work.css' import Cta from '../atoms/Cta' import Headphone from '../assets/images/headphones3.png' import Calendar from '../assets/images/calendar.png' import DevConnector from '../assets/images/dev.png' import Bulls from '../assets/images/bulls2.png' import Expenses from '../assets/images/reactExpenses.png' import SixFlags from '../assets/images/sixflags.png' import useDots from '../hooks/useDots'; const images = [Calendar, Headphone, SixFlags, DevConnector, Bulls, Expenses]; const Work = () => { const [activeIndex, setActiveIndex] = useDots(images.length); function handleDotClick(index) { console.log("Clicked dot with index:", index); setActiveIndex(index); const targetCard = document.querySelector(`[data-id="${index}"]`); console.log("Target card:", targetCard); if (targetCard) { const magicWall = document.getElementById('home-magicwall'); console.log("Magic wall:", magicWall); console.log("Target card offsetLeft:", targetCard.offsetLeft); console.log("Magic wall offsetLeft:", magicWall.offsetLeft); magicWall.scroll({ left: targetCard.offsetLeft - magicWall.offsetLeft, behavior: 'smooth' }); } } return ( <div className="main-container"> <section id="section-work"> <div id="header"> <h2>My Work</h2> </div> <div className="text-zone-2"> <div> <p> A small gallery of recent projects chosen by me. I've done them all together with amazing people from companies around the globe. It's only a drop in the ocean compared to the entire list. Interested to see some more? Visit my work page. <br /> </p> </div> <div className="btn-container"> <Cta className="btn" link="https://github.com/mateoghidini1998" content="See More" /> </div> </div> <div className="fake-big-2">Work</div> </section> <div className="dots"> {images.map((image, index) => ( <button key={index} className={`dot ${index === activeIndex ? 'active' : ''}`} onClick={() => handleDotClick(index)} ></button> ))} </div> <div id="home-magicwall" className="fake-magicwall"> <ul> {images.map((image, index) => ( <li key={index} className={`magic-wall_item ${index === activeIndex ? 'active' : ''}`}> <img src={image} alt="image" /> <div className="hover-content"></div> <a href="/" className="colorbox" data-id={index}></a> </li> ))} </ul> </div> </div> ); }; export default Work;
自定义Hook代码
import { useState } from 'react'; function useDots(images) { const [activeIndex, setActiveIndex] = useState(0); return [activeIndex, setActiveIndex]; } export default useDots;
排查情况
已通过console.log确认:
- 点击的点按钮索引正确
<a>标签的data-id属性值正确- 每次点击能输出
Target card offsetLeft: 133和Magic wall offsetLeft: 0
但滚动操作完全不生效。
原因分析
核心问题是滚动容器找错了:
你的CSS明确设置了.fake-magicwall ul的overflow-x: auto,也就是真正具备横向滚动能力的是<ul>元素;但当前代码中调用scroll()方法的是它的父元素#home-magicwall,这个父元素没有开启滚动属性,所以执行滚动操作不会有任何效果。
另外,你当前获取的目标元素是<a>标签,而它是<li>的子元素,基于子元素的offsetLeft计算滚动位置可能会有偏差,应该直接以<li>(卡片容器)作为目标参考。
解决方案
1. 修正滚动容器和目标元素
修改handleDotClick函数,将滚动容器改为<ul>,目标元素改为对应的<li>:
function handleDotClick(index) { console.log("Clicked dot with index:", index); setActiveIndex(index); // 改为获取对应的li元素(给li加上data-id属性) const targetLi = document.querySelector(`.magic-wall_item[data-id="${index}"]`); console.log("Target li:", targetLi); if (targetLi) { // 获取真正的滚动容器:ul元素 const scrollContainer = document.querySelector('#home-magicwall ul'); console.log("Scroll container:", scrollContainer); // 直接基于li的offsetLeft设置滚动位置 scrollContainer.scroll({ left: targetLi.offsetLeft, behavior: 'smooth' }); } }
2. 给<li>添加data-id属性
在渲染<li>时加上data-id={index},方便准确获取目标元素:
<li key={index} data-id={index} className={`magic-wall_item ${index === activeIndex ? 'active' : ''}`}> <img src={image} alt="image" /> <div className="hover-content"></div> <a href="/" className="colorbox"></a> </li>
3. 确保横向布局的完整性(可选)
如果<ul>和<li>的横向布局还存在问题,可以补充以下CSS:
.fake-magicwall ul { display: flex; /* 启用flex布局 */ gap: 10px; /* 卡片间间距,可根据需求调整 */ } .fake-magicwall li { flex-shrink: 0; /* 禁止卡片收缩,保证宽度一致 */ width: 200px; /* 设置卡片固定宽度,可根据需求调整 */ }
额外优化:使用React Ref替代DOM查询(推荐)
在React中直接操作DOM不是最佳实践,建议用useRef来获取滚动容器:
import React, { useRef } from 'react' const Work = () => { const [activeIndex, setActiveIndex] = useDots(images.length); const scrollRef = useRef(null); // 创建ref function handleDotClick(index) { setActiveIndex(index); const targetLi = scrollRef.current.children[index]; // 通过ref直接获取子元素 if (targetLi && scrollRef.current) { scrollRef.current.scroll({ left: targetLi.offsetLeft, behavior: 'smooth' }); } } return ( // ...其他代码 <div id="home-magicwall" className="fake-magicwall"> <ul ref={scrollRef}> {/* 绑定ref到ul */} {/* ...li元素 */} </ul> </div> // ...其他代码 ) }
内容的提问来源于stack exchange,提问作者tukitooo1998
相关产品推荐
相关产品推荐

