【React开发定式】返回自动滚动到上次浏览位置
我是銀桑,希望能帮到你。
一句话总结
通过Route内的一个定制组件来记录当前页面滚动位置,在实际页面渲染完后的恰当时机,通过context执行滚动到记录位置的函数。
缘起
在使用React Router的项目开发中,返回时定位到上次浏览位置是非常常见的交互,而官方并没有明确应该如何实现。
原理介绍
以最常见的HashRouter为例,
<HashRouter>
<PageIndex/>
</HashRouter>
在PageIndex外包一层组件ScrollToPosition 用来记录窗口的位置。则有了以下代码。
ReactDOM.render(
<HashRouter >
<ScrollToPosition>
{renderRoutes(routesConfig)}
</ScrollToPosition>
</HashRouter>
document.getElementById('app')
);
ScrollToPosition的代码如下
import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import _ from 'lodash'
import { PageScrollContext } from '@/components/context';
const ScrollToPosition = ({ children }) => {
const location = useLocation();
const { pathname } = location;
const scrollTo = () => {
const scrollY = sessionStorage.getItem(pathname);
// 为了避免scrollY为0引起的滚动到顶部后没有记录的bug,将交互改为在150px内直接滚动到顶部
if (scrollY) {
const scrollResult = Number(scrollY) < 150 ? 0 : Number(scrollY);
window.scrollTo(0, scrollResult);
// 路由切换时重新绑定一次最新的pathname
useEffect(() => {
const scrollHandler = util.throttle(() => {
// 点击切换路由时会触发一次scroll,此时 scrollY为0
if (window.scrollY > 0) {
sessionStorage.setItem(pathname, String(window.scrollY));
window.addEventListener('scroll', scrollHandler);
return () => {
// 做好清理
window.removeEventListener('scroll', scrollHandler);
}, [pathname]);
return (
<PageScrollContext.Provider value={scrollTo}>
{children}
</PageScrollContext.Provider>
export default ScrollToPosition;
context 自然就定义如下
export const PageScrollContext = React.createContext(() => {});
因一般页面是根据接口渲染,所以需要在合适的时机调用PageScrollContext对应的函数。
import { PageScrollContext } from '@/components/context';