当前位置: 首页 > news >正文

react-activation 实现页面保活记录

这里写目录标题

    • 一、安装插件(可选)
        • 1、react-activation (推荐)
        • 2、umi-plugin-keep-alive
    • 二、AliveScope的两种配置方式
        • 1、在src/app.ts 中配置
        • 2、在src/layout/index.tsx中配置
    • 三、umi中的配置
    • 四、使用问题记录
        • 1、`drop`使用不生效,使用`setTimeout`
        • 2、`refresh`在页面mounted之前执行
    • 参考

一、安装插件(可选)

1、react-activation (推荐)
npm install react-activation
2、umi-plugin-keep-alive

这个插件也是基于react-activation

npm install umi-plugin-keep-alive --save

使用:

import { KeepAlive } from 'umi'
const contentList = () => {
	return (
		<KeepAlive 
			name="/About" //可按照name卸载缓存状态下的 <KeepAlive> 节点
			saveScrollPosition="screen" //自动保存共享屏幕容器的滚动位置
			when={true} >  //true卸载时缓存,false卸载时不缓存
       		{/*要保存状态的组件*/}

		</KeepAlive>
	)
}

但我使用umi4搭建的项目,在安装该插件后,umi没有导出KeepAlive,无法使用,所以直接用的第一种

二、AliveScope的两种配置方式

保证AliveScope稳定

1、在src/app.ts 中配置

配置文档: https://umijs.org/docs/api/runtime-config

import React from 'react';
import { AliveScope } from 'react-activation';

// 修改交给 react-dom 渲染时的根组件, 在外层包裹AliveScope
export function rootContainer(container: any) {
  return React.createElement(AliveScope, null, container);
}

然后在需要的组件外层包裹KeepAlive

import KeepAlive from "react-activation";
function Test() {
	return (
	  <KeepAlive>
	    {/*页面组件*/}
	  </KeepAlive>
	);
}


// 如果有connect函数的可以如下写法:
const DataMine = connect(({ user }) => ({ user }))(Mine)
export default () => <KeepAlive><DataMine/></KeepAlive>;
2、在src/layout/index.tsx中配置
export default function Layout(props: any) {
  return (
    <AliveScope>
    {/*页面组件*/}
    </AliveScope>
  )
}

三、umi中的配置

umi 的 babel 配置要加在config.js文件中

  extraBabelPlugins: ['react-activation/babel']

四、使用问题记录

1、一个组件设置keepAlive,它的某个子组件A也设置KeepAlive, 跳转到其他页面再跳回该页面,A不见了

2、在某些组件不需要保活的时候,通过drop、refresh等方式去清掉某个缓存,这里要注意:

1、drop使用不生效,使用setTimeout
import { useAliveController } from 'react-activation';
const { drop, dropScope, refresh } = useAliveController();

// 示例一: 要在跳转该页面之前执行,需要延时, 去掉setTimeout,drop不生效
drop('testName');
setTimeout(() => {
  history.push('/test');
}, 50);

// 示例二: 在useUnactivate中使用
useUnactivate(() => {
// 在某个条件下退出要清除缓存
	if(xxxx) {
		setTimeout(() => dropScope('testName'), 0)
	}
})

2、refresh在页面mounted之前执行
refresh('testName')

但这里有个小坑,refresh会重新刷新页面,但是不会重新去拿页面的url,也就是说如果你的某些逻辑依赖于url的query字段,需要修改一下获取

import { useSearchParams, history } from 'umi';

// 原本代码
const Test = (props) => {
  const [params] = useSearchParams();
  // params.get('xxx') 获取参数去处理
};

// 修改为:
const Test = (props) => {
  const url = window.location.href;
  const params = (new URL(url)).searchParams;
  // params.get('xxx') 获取参数去处理
};

3、滚动条的位置问题
当在两个已经缓存的页面跳转时,滚动条位置是保持的,
但当从一个页面去到一个未保活的页面,第一次跳转原页面的滚动条位置未保持,第二次跳转才保持


// KeepAlive组件增加saveScrollPosition=参数
<KeepAlive saveScrollPosition={true} />

// 如果组件共享了屏幕滚动容器如 document.body 或 document.documentElement, 将 saveScrollPosition 属性设置为 “screen”

<KeepAlive saveScrollPosition="screen" />

解决方案
自定义keep.ts方法,监听每个页面的滚动位置,并在回到该页面时滚回上次记录点。

import _ from 'lodash';
import { history } from 'umi';

interface PageItem {
  ele: Element; // 元素
  y: number; // 竖向位置
}
interface PageLocationProps {
  [key: string]: PageItem;
}
// 获取初始的路由
let pName = history.location.pathname;

// 存储每个页面的滚动ele和top距离
let scrollLoction: PageLocationProps = {};

// 滚动记录页面的ele和距离
const handleScroll = _.debounce(
  (e) => {
    if (!scrollLoction[pName]) {
      scrollLoction[pName] = {} as PageItem;
    }
    scrollLoction[pName].ele = e.target;
    scrollLoction[pName].y = e.target.scrollTop;
  },
  500,
  { leading: false, trailing: true },
);

// 路由监听,判断是否回滚到之前的位置
const unlisten = history.listen((route) => {
  pName = route.location.pathname;
  if (pName in scrollLoction) {
    // 在页面加载出来之后,放在宏任务中即可, 时间为0也是可以的
    setTimeout(() => {
      // 如果相等,就不需要在再次scrollTo
      if (scrollLoction[pName] && scrollLoction[pName].ele.scrollTop !== scrollLoction[pName].y) {
        // console.log('手动滚动', scrollLoction[pName].y);
        scrollLoction[pName].ele.scrollTo(0, scrollLoction[pName].y);
      }
    }, 300);
  }
});

// 在pc端可以,在移动端发现onload,和onbeforeunload监听都无效
// 添加监听事件
window.addEventListener('scroll', handleScroll, true);

// 卸载: 移除相关引用和监听
window.addEventListener('beforeunload', () => {
  scrollLoction = {};
  unlisten();
  window.removeEventListener('scroll', handleScroll, true);
});

在app.ts中

// react-activation 从当前页跳转到未加载的页面时,没有保存位置, js修复
// 比如: 从看板详情到指标详情, 返回后,发现滚动位置没有保存,但第二次进入指标详情返回后有保存
import '@/utils/keep';

参考

react16路由缓存react-activation详解

相关文章:

  • 前端模拟 websocket 请求小工具
  • mac vim命令快捷键
  • LeetCode热题100精讲——Top7:接雨水【双指针】
  • 树莓派5-GPIO和40针引脚
  • redis使用
  • 手动创建kkFileView4.4.0镜像
  • C#基础学习(二)C#数组生存手册:从入门到“血压拉满“的奇妙旅程
  • Socket如何实现客户端和服务器间的通信
  • 23种设计模式中的责任链模式
  • 7.1-7.2考研408数据结构查找算法核心知识点深度解析
  • PyTorch 深度学习实战(21):元强化学习与 MAML 算法
  • 从零构建大语言模型全栈开发指南:第一部分:数学与理论基础-1.1.3模型参数与超参数:权重、偏置、学习率与正则化策略
  • git-lfs: command not found
  • reactor网络模型
  • JAVA:Spring Boot @Conditional 注解详解及实践
  • redis+spring 的基本操作 RedisTemplate和RedisClient
  • phpcms版AI自动发文插件,自动创作,自动配图,自动发布,支持多种大模型
  • 网络编程和计算机网络五层模型的关系
  • 数据结构练习二习题
  • qt QOffscreenSurface详解
  • 出口网站有哪些/seo百度网站排名软件
  • 网站建设合同注意点/网上营销网站
  • 家政网站怎么做/网络平台推广运营有哪些平台
  • 天津网站建设市场/深圳百度推广电话
  • 网站轮播图能用什么软件做/百度搜索seo
  • 宁波海曙网站开发公司/河南百度seo