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


当前回答

值得注意的是onUpdate={() =>窗口。scrollTo(0,0)}方法过时。

下面是react-router 4+的一个简单解决方案。

const history = createBrowserHistory()

history.listen(_ => {
    window.scrollTo(0, 0)  
})

<Router history={history}>

其他回答

这是另一种方法。

对于react-router v4,您还可以以以下方式将侦听器绑定到历史事件中的change:

let firstMount = true;
const App = (props) => {
    if (typeof window != 'undefined') { //incase you have server-side rendering too             
        firstMount && props.history.listen((location, action) => {
            setImmediate(() => window.scrollTo(0, 0)); // ive explained why i used setImmediate below
        });
        firstMount = false;
    }

    return (
        <div>
            <MyHeader/>            
            <Switch>                            
                <Route path='/' exact={true} component={IndexPage} />
                <Route path='/other' component={OtherPage} />
                // ...
             </Switch>                        
            <MyFooter/>
        </div>
    );
}

//mounting app:
render((<BrowserRouter><Route component={App} /></BrowserRouter>), document.getElementById('root'));

如果点击链接改变了路由,那么没有setimmediation(),滚动级别也会被设置为0,但是如果用户在浏览器上按下后退按钮,那么它将不起作用,因为浏览器在按下后退按钮时手动将滚动级别重置到上一个级别,所以通过使用setimmediation(),我们使我们的函数在浏览器完成重置滚动级别后执行,从而给我们提供了预期的效果。

钩子是可组合的,从React Router v5.1开始,我们就有了一个useHistory()钩子。所以基于@zurfyx的答案,我为这个功能创建了一个可重用的钩子:

// useScrollTop.ts
import { useHistory } from 'react-router-dom';
import { useEffect } from 'react';

/*
 * Registers a history listener on mount which
 * scrolls to the top of the page on route change
 */
export const useScrollTop = () => {
    const history = useHistory();
    useEffect(() => {
        const unlisten = history.listen(() => {
            window.scrollTo(0, 0);
        });
        return unlisten;
    }, [history]);
};

这个答案是遗留代码,对于路由器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;
  }
}

在router.js中,只需在router对象中添加这个函数。这个就行了。

scrollBehavior() {
        document.getElementById('app').scrollIntoView();
    },

像这样,

* * Routes.js * *

import vue from 'blah!'
import Router from 'blah!'

let router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    scrollBehavior() {
        document.getElementById('app').scrollIntoView();
    },
    routes: [
            { url: "Solar System" },
            { url: "Milky Way" },
            { url: "Galaxy" },
    ]
});

我的申请也遇到了同样的问题。使用下面的代码片段可以帮助我在单击下一个按钮时滚动到页面顶部。

<Router onUpdate={() => window.scrollTo(0, 0)} history= {browserHistory}>
...
</Router>

然而,在浏览器返回时,这个问题仍然存在。经过大量的尝试,我意识到这是因为浏览器窗口的历史对象,它有一个属性scrollRestoration被设置为auto。将此设置为手动解决了我的问题。

function scrollToTop() {
    window.scrollTo(0, 0)
    if ('scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
    }
}

<Router onUpdate= {scrollToTop} history={browserHistory}>
....
</Router>