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]); // 页面完成的上下文和是否为返回上一页的上下文
5.所用到的函数代码
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的使用保存可看下文