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的使用保存可看下文

跳转~~

 

posted @ 2023-03-23 15:42  马铃薯头抽雪茄  阅读(1022)  评论(0)    收藏  举报