我有一个问题,当导航到另一个页面,它的位置将保持像之前的页面。所以它不会自动滚动到顶部。 我也试过使用window。onChange路由器上的scrollTo(0,0)。我还使用了scrollBehavior来修复这个问题,但它没有工作。对此有什么建议吗?
当前回答
对于我的应用程序,当通过链接导航时,有能力向上滚动是很重要的。但在点击标签(也是链接)时,不要滚动任何东西也是很重要的。此外,我的应用程序有一个先进的布局,因此可滚动的容器可以根据当前页面的布局和链接的位置而不同。
下面是我的解决方案:
为react-router-dom添加onClick处理程序的Link引入RouterLink包装器。当链接被单击时,它会找到最近的滚动容器并向上滚动。可以通过指定preservesroll(这是原始Link的默认行为)来选择退出此行为。
希望这能有所帮助。
// Helper to find nearest scrolled parent of a given node
const getScrollParent = (node) => {
if (!node) {
return null;
}
if (node.scrollTop > 0) {
return node;
} else {
return getScrollParent(node.parentNode);
}
};
interface RouterLinkProps extends LinkProps {
preserveScroll?: boolean;
}
export const RouterLink: React.FC<RouterLinkProps> = ({ preserveScroll = false, ...linkProps }) => {
const handleClick = useCallback(
(val) => {
const targetEl = val?.target;
if (!targetEl || preserveScroll) {
return;
}
const scrolledContainer = getScrollParent(targetEl);
if (scrolledContainer) {
scrolledContainer.scrollTo({
top: 0,
left: 0,
behavior: 'smooth',
});
}
},
[preserveScroll],
);
const extraProps = useMemo(() => {
if (!preserveScroll) {
return {
onClick: handleClick,
};
}
return {};
}, [handleClick, preserveScroll]);
return <Link {...linkProps} {...extraProps} />;
};
现在,我可以使用这个包装器并获得所需的行为和足够的控制来调整它。是这样的:
<RouterLink to="/some/path">我向上滚动的链路</RouterLink> .
其他回答
我发现ReactDOM.findDomNode(this). scrollintoview()正在工作。我把它放在componentDidMount()中。
但是课程太2018年了
ScrollToTop实现与React挂钩
ScrollToTop.js
import { useEffect } from 'react';
import { withRouter } from 'react-router-dom';
function ScrollToTop({ history }) {
useEffect(() => {
const unlisten = history.listen(() => {
window.scrollTo(0, 0);
});
return () => {
unlisten();
}
}, []);
return (null);
}
export default withRouter(ScrollToTop);
用法:
<Router>
<Fragment>
<ScrollToTop />
<Switch>
<Route path="/" exact component={Home} />
</Switch>
</Fragment>
</Router>
ScrollToTop也可以实现为一个包装器组件:
ScrollToTop.js
import React, { useEffect, Fragment } from 'react';
import { withRouter } from 'react-router-dom';
function ScrollToTop({ history, children }) {
useEffect(() => {
const unlisten = history.listen(() => {
window.scrollTo(0, 0);
});
return () => {
unlisten();
}
}, []);
return <Fragment>{children}</Fragment>;
}
export default withRouter(ScrollToTop);
用法:
<Router>
<ScrollToTop>
<Switch>
<Route path="/" exact component={Home} />
</Switch>
</ScrollToTop>
</Router>
使用useEffect() -功能组件的解决方案
useEffect(() => {
window.history.scrollRestoration = 'manual';}, []);
这个答案是遗留代码,对于路由器v4+检查其他答案
<Router onUpdate={() => window.scrollTo(0, 0)} history={createBrowserHistory()}>
...
</Router>
如果它不起作用,你应该找到原因。同样在componentDidMount内部
document.body.scrollTop = 0;
// or
window.scrollTo(0,0);
你可以用:
componentDidUpdate() {
window.scrollTo(0,0);
}
你可以添加一些像" scrolling = false"这样的标志,然后在update中:
componentDidUpdate() {
if(this.scrolled === false){
window.scrollTo(0,0);
scrolled = true;
}
}
2022年11月更新
在react最新版本18.2.0和react-router-dom 6.4.3中没有任何工作。所以我实现了这个。为我工作。希望这对大家有帮助。
ScrollToTop.js
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
const body = document.querySelector('#root');
body.scrollIntoView({
behavior: 'smooth'
}, 500)
}, [pathname]);
return null;
}
然后在index.js或App.js中导入并添加到浏览器路由器,在那里定义路由。
import { BrowserRouter, Routes, Route } from "react-router-dom";
import ScrollToTop from "./ScrollToTop";
function App() {
return (
<div>
<BrowserRouter>
<ScrollToTop />
<Routes>
//your routes
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
(注意:确保index.html div id="root"。)