react回退上一页到原来位置
1.准备用到的数据
import React, { useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { useLocation } from 'react-router-dom'; // 获取路径
import _ from 'lodash'; // 用于节流
import smoothscroll from 'smoothscroll-polyfill'; // 兼容
import GlobalStateContext from 'components/GlobalStateContext'; // 用于获取上下文保存的参数
const [roll, setRoll] = useState(false); // 用于判断页面是否有滚动过 如果有取消回到上一次的滚动位置
const location = useLocation(); // 获取路由
const Context = useContext(GlobalStateContext); // 获取同于存储的上下文
2.做一个监听的页面滚动的函数放到sessionStorage里
const scrollHandler = () => {
if (misc.getScroll().top > 0) { // 获取滚动距离的函数下面放出
sessionStorage.setItem(location.pathname, String(misc.getScroll().top));
setRoll(() => true); // 如果距离发生了变化 那么代表已经滚动了 那就变成true不用再执行回到上一次页面位置的操纵
}
};
const scrollHandlerThrottle = _.throttle(scrollHandler, 100); // 节流
3.使用useEffect做一个监听路由
用于在每次跳转时判断当前是否为浏览器点击的返回上一页
React.useEffect(() => {
misc.GoBackTop('0'); // 这个是回到顶部的函数 后面放出
if (!Context.globalState.PageComplete) {
misc.scrollToView(); // 这个是回到顶部的函数 后面放出
}
if (window.history && window.history.pushState) { // 这里判断他是否为返回上一步的操纵, 是的话就直接进行修改上下文的状态复制
window.onpopstate = function () {
Context.globalStateDispatch({ type: 'setRetreat', retreat: true });
};
}
window.addEventListener('scroll', scrollHandlerThrottle, true); // 监听页面滚动
return () => {
window.removeEventListener('scroll', scrollHandlerThrottle, true);
// 路劲变换都修改为默认值
setRoll(() => false);
Context.globalStateDispatch({ type: 'setRetreat', retreat: false });
Context.globalStateDispatch({ type: 'setPageComplete', PageComplete: false });
};
}, [location]);
4.监听页面的加载完成还有为返回上一步的操纵后索要执行的代码
React.useEffect(() => {
if (Context.globalState.retreat) {
const scrollY = sessionStorage.getItem(location.pathname);
if (scrollY) { // 查看是否有当前页面的滚动距离的值存放再sessionStorage
const scrollResult = Number(scrollY) < 150 ? 0 : Number(scrollY);
if (Context.globalState.PageComplete && !roll && Context.globalState.retreat) {
misc.scrollToView(scrollResult);// 滚动的函数
Context.globalStateDispatch({ type: 'setRetreat', retreat: false });
} else if (Context.globalState.PageComplete && !Context.globalState.retreat && !roll) {
misc.scrollToView(0); // 滚动的函数
}
} else {
misc.scrollToView(0); // 滚动的函数
}
}
return () => {
};
}, [Context.globalState.PageComplete, Context.globalState.retreat]); // 页面完成的上下文和是否为返回上一页的上下文
// Context.globalState.PageComplete 当每个页面加载完成时会发生改变
5.1.把他们包起来
const ScrollRestoration = ({ children }) => {
// 放入上面 1.2.3.4代码
};
export default ScrollRestoration;
5.2.把他放到外面包起来
import ScrollRestoration from '../ScrollRestoration';
// 包到组件外 每一次切换页面都会先走一遍
<ScrollRestoration>
<AppComponent />
</ScrollRestoration>
6.所用到的函数代码
sineaseOut(t, b, c, d) {
const val = c * ((t = t / d - 1) * t * t + 1) + b;
return val;
},
linear(t, b, c, d) { // 匀速
return ((c * t) / d) + b;
},
scrollToView(value, time, Bool) {
// if (!scroller) {
// return;
// }
if (value) {
const scroll = value;
const scrollStart = 0;
let start = null;
const step = (timestamp) => {
if (!start) {
start = timestamp;
}
const stepScroll = !Bool ? this.sineaseOut(timestamp - start, 0, scroll, time || 500) : this.linear(timestamp - start, 0, scroll, time || 500);
document.body.scrollTop = scrollStart + stepScroll;
const total = document.body.scrollTop;
if (total < scrollStart + scroll) {
aa = requestAnimationFrame(step);
}
};
aa = requestAnimationFrame(step);
} else {
cancelAnimationFrame(aa);
}
}
=========================================
GoBackTop(Value) {
if (Value) {
document.body.scrollTop = Value;
document.documentElement.scrollTop = Value;
} else {
document.body.scrollTop = 150;
document.documentElement.scrollTop = 150;
}
}
=========================================
getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || window.scrollY || 0,
};
}
6.后言
关于使用存储的上下文
GlobalStateContext的使用保存可看下文

浙公网安备 33010602011771号