如何禁用React Router中ScrollRestoration的平滑滚动行为?
让React Router ScrollRestoration跳过全局平滑滚动的实现方法
你可以通过临时覆盖全局的scroll-behavior属性,让ScrollRestoration触发的滚动使用即时效果,滚动完成后再恢复平滑滚动。具体实现如下:
自定义ScrollRestoration组件
创建一个自定义组件包裹官方的ScrollRestoration,在路由切换时临时禁用平滑滚动:
import { ScrollRestoration, useLocation } from 'react-router-dom'; import { useEffect, useRef } from 'react'; const CustomScrollRestoration = () => { const location = useLocation(); const prevLocation = useRef(null); useEffect(() => { // 排除首次加载,仅在路由切换时执行 if (prevLocation.current) { const htmlElement = document.documentElement; // 临时设置为即时滚动 htmlElement.style.scrollBehavior = 'auto'; // 滚动完成后恢复平滑滚动 const resetScrollBehavior = () => { htmlElement.style.scrollBehavior = 'smooth'; window.removeEventListener('scroll', resetScrollBehavior); }; // 监听滚动完成事件(仅触发一次) window.addEventListener('scroll', resetScrollBehavior, { once: true }); // 兜底处理:防止滚动事件未触发的情况 const timeoutId = setTimeout(() => { htmlElement.style.scrollBehavior = 'smooth'; }, 100); // 清理函数 return () => { window.removeEventListener('scroll', resetScrollBehavior); clearTimeout(timeoutId); htmlElement.style.scrollBehavior = 'smooth'; }; } prevLocation.current = location; }, [location]); return <ScrollRestoration />; }; export default CustomScrollRestoration;
替换官方组件
在你的路由配置中,用自定义的CustomScrollRestoration代替官方的ScrollRestoration:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import CustomScrollRestoration from './CustomScrollRestoration'; function App() { return ( <Router> <CustomScrollRestoration /> <Routes> {/* 你的路由配置 */} <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </Router> ); }
原理说明
- 当路由切换时,临时将
html元素的scroll-behavior设为auto,此时ScrollRestoration触发的页面滚动会使用浏览器默认的即时行为。 - 通过监听
scroll事件(设置once: true确保只执行一次),滚动完成后恢复scroll-behavior: smooth,不影响用户手动触发的平滑滚动。 - 增加
setTimeout兜底,避免某些场景下滚动事件未触发导致平滑滚动无法恢复的问题。
内容的提问来源于stack exchange,提问作者tguichaoua
相关产品推荐
相关产品推荐

