React中如何设置组件默认滚动位置且不滚动整个页面
解决日历组件独立滚动不影响父页面的问题
你的核心问题是日历容器未被设置为独立滚动容器,导致调用滚动操作时实际触发了父页面的滚动;同时浏览器的滚动冒泡机制会优先滚动父元素到边界后再处理子元素。以下是具体解决方法:
1. 将日历容器设为独立滚动上下文
给日历容器添加overflow-y: auto(或overflow-y: scroll)样式,让它拥有自己的滚动区域,内部滚动不会影响父页面:
<div ref={calendarRef} style={{ scrollMarginTop: '1000px', height: '700px', position: 'relative', marginLeft: '40px', overflowY: 'auto', // 关键:开启垂直滚动 overflowX: 'hidden', // 可选:隐藏水平滚动条 }} >
2. 优化滚动触发逻辑
确保DOM完全渲染后再执行滚动操作,避免容器未就绪导致的异常;同时通过聚焦容器阻止滚动冒泡到父页面:
useEffect(() => { const scrollCalendar = () => { if (calendarRef.current) { calendarRef.current.focus(); // 聚焦容器,隔离父页面滚动 calendarRef.current.scrollTo({ top: 500, behavior: 'auto' // 禁用动画,避免滚动链触发父页面 }); } }; // 等待DOM渲染完成 requestAnimationFrame(scrollCalendar); }, []);
3. 额外适配:让容器可聚焦
给日历容器添加tabIndex="-1"属性,使其成为可聚焦元素,确保focus()方法生效:
<div ref={calendarRef} tabIndex="-1" style={{/* ...其他样式 */}} >
修改后的完整组件代码
export default function WeeklyCalendar({classes, clinicals, blockedTime, fileClinicalList}) { const calendarRef = useRef(null); useEffect(() => { const scrollCalendar = () => { if (calendarRef.current) { calendarRef.current.focus(); calendarRef.current.scrollTo({ top: 500, behavior: 'auto' }); } }; requestAnimationFrame(scrollCalendar); }, []); return ( <div> <div style={{ position: 'sticky', zIndex: '10', backgroundColor: PlatformStyles.LogoNavyBlue, width: '100%', top: '0px', left: '-10%', right: '50px', fontWeight: 'bold' }} > {days.map((day , index) => { let width = columnWidth if (index === 0) { width = '5%' } return ( <div style={{ position: '', display: 'inline-block', zIndex: 11, color: 'white', width, textAlign: 'center' }} > {day} </div> ) })} </div> <div ref={calendarRef} tabIndex="-1" style={{ scrollMarginTop: '1000px', height: '700px', position: 'relative', marginLeft: '40px', overflowY: 'auto', overflowX: 'hidden' }} > {hours.map((hour) => { let id = hour if (hour === 6) { id = 'scrollId' } return ( <div key={hour} id={id} style={{ position: 'absolute', top: `${(hour - 0.5) * multiplier + .51}%`, bottom: `${100 - (hour + 1) * multiplier}%`, left: '-2%', right: '0%', fontSize: '11px', textAlign: 'left', fontWeight: 'bold', alignItems: 'center' }} > {convertTime(hour)} </div> ) })} {/* Adds line in the middle of the hour */} {hours.map((hour) => <div key={hour} style={{ position: 'absolute', top: `${hour * multiplier}%`, bottom: `${100 - (hour + 1) * multiplier}%`, left: '.5%', right: '0%', marginLeft: '22px', borderBottom: '1px solid lightgray', textAlign: 'left', fontWeight: 'bold', alignItems: 'center' }} > </div> )} {events.map((event, index) => event.day.map((day) => <Event key={`event-${index}-${day}`} event={event} day={day} /> ) )} </div> </div> ) }
内容的提问来源于stack exchange,提问作者Mike Greco
相关产品推荐
相关产品推荐

