我有一个问题,当导航到另一个页面,它的位置将保持像之前的页面。所以它不会自动滚动到顶部。 我也试过使用window。onChange路由器上的scrollTo(0,0)。我还使用了scrollBehavior来修复这个问题,但它没有工作。对此有什么建议吗?


当前回答

对我来说,是窗户。scrollTo(0,0)和document.documentElement。scrollTo(0,0)没有在我的所有屏幕上工作(只在一个屏幕上工作)。

然后,我意识到我的屏幕的溢出(滚动是允许的)不在窗口(因为我们有一些静态点,所以我们把溢出:auto在其他div)。

为了实现这一点,我做了以下测试:

useEffect(() => {
  const unlisten = history.listen(() => {
    console.log(document.documentElement.scrollTop)
    console.log(window.scrollTop)
    window.scrollTo(0, 0);
  });
  return () => {
    unlisten();
  }
}, []);

在所有的对数中,我得到0。

所以,我寻找我有滚动的容器,并放置一个id:

<div id="SOME-ID">
    ...
</div>

在我的ScrollToTop组件中,我放入:

useEffect(() => {
  const unlisten = history.listen(() => {
    window.scrollTo(0, 0);
    document.getElementById("SOME-ID")?.scrollTo(0, 0)
  });
  return () => {
    unlisten();
  }
}, []);

现在,当我用history.push("/SOME-ROUTE")转到一条新路线时,我的屏幕会转到顶部

其他回答

这个答案只适用于v4版本,而不适用于后续版本。

React Router v4的文档包含了用于滚动恢复的代码示例。下面是他们的第一个代码示例,它作为一个全站解决方案,当页面导航到“滚动到顶部”:

class ScrollToTop extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      window.scrollTo(0, 0)
    }
  }

  render() {
    return this.props.children
  }
}

export default withRouter(ScrollToTop)

然后在你的应用程序的顶部渲染它,但在路由器下面:

const App = () => (
  <Router>
    <ScrollToTop>
      <App/>
    </ScrollToTop>
  </Router>
)

// or just render it bare anywhere you want, but just one :)
<ScrollToTop/>

^直接从文档中复制

显然,这适用于大多数情况,但是关于如何处理选项卡接口以及为什么没有实现通用解决方案还有更多内容。

平滑滚动选项

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo({
      top: 0,
      left: 0,
      behavior: 'smooth', 
    });
  }, [pathname]);

  return null;
}

...

<Router>
      <ScrollToTop />
     ...
    </Router>

对于我的应用程序,当通过链接导航时,有能力向上滚动是很重要的。但在点击标签(也是链接)时,不要滚动任何东西也是很重要的。此外,我的应用程序有一个先进的布局,因此可滚动的容器可以根据当前页面的布局和链接的位置而不同。

下面是我的解决方案:

为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> .

2021年8月,

而不是在每个页面都这样做,你可以在App.js中这样做

import { useLocation } from "react-router-dom";

const location = useLocation();
useEffect(() => {
  window.scrollTo(0,0);
}, [location]);

在useEffect中设置位置将确保每次路径更改时滚动到顶部。

我发现ReactDOM.findDomNode(this). scrollintoview()正在工作。我把它放在componentDidMount()中。