react16路由缓存react-activation详解

react PC端项目构建TS,react@18.2.0+antd+vite+axios+redux+sass+ts 完整版代码下载:
https://download.csdn.net/download/randy521520/88922625
react PC端项目构建,react@18.2.0+antd+vite+axios+redux+sass完整版代码下载:
https://download.csdn.net/download/randy521520/88922569
react移动端项目构建TS,react@18.2.0+react-vant+vite+axios+redux+sass+ts完整版代码下载:
https://download.csdn.net/download/randy521520/88917557
react移动端项目构建,react@18.2.0+react-vant+vite+axios+redux+sass完整版代码下载:
https://download.csdn.net/download/randy521520/88917543

一、简介

React 路由缓存是指在使用 React Router 或其他路由管理库时,通过一些技术手段来缓存已经加载的页面组件,以便在用户再次访问这些页面时能够更快地呈现内容,提升用户体验和性能。
在这里插入图片描述

二、配置路由缓存

1.router.jsx,创建路由

import {Suspense, lazy} from "react";
import {Navigate, useRoutes} from "react-router-dom";
import KeepAlive from "react-activation";

const routes = [{
    path: '/',
    element: <Navigate to="/home" replace/>,
}, {
    id: "home",
    path: '/home',
    component: lazy(() => import('@pages/home/home.jsx'))
}, {
    id: "list",
    path: '/list',
    component: lazy(() => import('@pages/list/list.jsx'))
}];

const generateRouter = (routers) => {
    return routers.map((item) => {
        if (item.children) {
            item.children = generateRouter(item.children)
        }
        item.element = <KeepAlive cacheKey={item.path} id={item.path} name={item.path}>
            <Suspense>
                {item.component ? <item.component/> : item.element}
            </Suspense>
        </KeepAlive>;
        return item
    })
};

const RootRouter = () => useRoutes(generateRouter(routes));

export default RootRouter;

2.App.jsx,使用路由

import RootRouter from "@/router.jsx";

function App() {
    return (
        <>
            <RootRouter/>
        </>
    )
}

export default App

3.main.js,使用路由缓存

import ReactDOM from "react-dom/client";
import {BrowserRouter} from "react-router-dom";
import App from "./App.jsx";
import {AliveScope} from "react-activation";

ReactDOM.createRoot(document.getElementById('root')).render(
  <BrowserRouter>
      <AliveScope>
          <App />
      </AliveScope>
  </BrowserRouter>,
)
三、路由缓存生命周期

1.useActivate(()=>{}):组件激活,第一次进入组件,不会进入该生命周期,因为组件未缓存
2.useUnactivate(()=>{}): 组件离开,缓存组件
3.案例,class组件可使用componentDidActivate 与 componentWillUnactivate

import {useActivate, useUnactivate} from "react-activation";
import {useState} from "react";
import {useNavigate} from "react-router-dom";

const Home = () => {
    const navigate = useNavigate();
    let [count, setCount] = useState(0);
    useActivate(() => {
        console.log('组件已激活')
    })
    useUnactivate(() => {
        console.log('组件已缓存')
    })
    const onCountChange = ()=>{
        count++;
        console.log(`count值:${count}`)
        setCount(count)
    }

    const goRouter = ()=>{
        navigate('/list')
    }

    return (<>
        <button onClick={onCountChange}>count改变</button>
        <button onClick={goRouter}>跳转list</button>
        <div>count值:{count}</div>
    </>)
}

export default Home;

在这里插入图片描述在这里插入图片描述

四、手动控制缓存

1.const { drop, dropScope, refresh,refreshScope,clear, getCachingNodes } = useAliveController()

  • drop(name):卸载缓存,需给<KeepAlive>加上name,如果没有缓存但是需要清除缓存状态需使用refresh(name)。仅卸载命中 <KeepAlive> 的第一层内容,不会卸载 <KeepAlive> 中嵌套的、未命中的<KeepAlive>
  • dropScope(name):卸载缓存,,需给<KeepAlive>加上name,如果没有缓存但是需要清除缓存状态需使用refresh(name)。将卸载命中 <KeepAlive> 的所有内容,包括 <KeepAlive> 中嵌套的所有 <KeepAlive>
  • refresh(name):刷新缓存,仅刷新命中 <KeepAlive> 的第一层内容,不会刷新 <KeepAlive> 中嵌套的、未命中的 <KeepAlive>
  • refreshScope(name):刷新缓存,将刷新命中<KeepAlive> 的所有内容,包括 <KeepAlive> 中嵌套的所有 <KeepAlive>
  • clear():将清空所有缓存中的 KeepAlive
  • getCachingNodes():获取所有缓存中的节点
    2.class组件需使用withAliveScope装饰器
@withAliveScope
class App extends Component {
  render() {
    const { drop, dropScope, clear, getCachingNodes } = this.props

    return (
      ...
    )
  }
}
五、自动缓存

给需要控制缓存的 <KeepAlive /> 标签增加 when 属性
1.当 when 类型为 Boolean 时

  • true: 卸载时缓存
  • false: 卸载时不缓存
<KeepAlive when={true}>

2.当 when 类型为 Array 时

  • 第 1 位参数表示是否需要在卸载时缓存
  • 第 2 位参数表示是否卸载 <KeepAlive> 的所有缓存内容,包括 <KeepAlive> 中嵌套的所有 <KeepAlive>
<KeepAlive when={[false, true]}>
   <KeepAlive>...</KeepAlive>
</KeepAlive>

3.当 when 类型为 Function 时,可返回Boolean或 Array

<KeepAlive when={() => true}>
<KeepAlive when={() => [false, true]}>
六、多份缓存,用于动态参数的路由

1./item 路由会按 id 来做不同呈现,但只能保留同一份缓存

<Route
path="/item/:id"
  render={props => (
    <KeepAlive>
      <Item {...props} />
    </KeepAlive>
  )}
/>

2.解决方法,给KeepAlive增加id

<Route
  path="/item/:id"
  render={props => (
    <KeepAlive id={props.match.params.id}>
      <Item {...props} />
    </KeepAlive>
  )}
/>
七、保存滚动位置

1.KeepAlive组件增加saveScrollPosition=参数

<KeepAlive saveScrollPosition={true} />

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

<KeepAlive saveScrollPosition="screen" />
八、使用react-activation存在的问题

1.<KeepAlive /> 中需要有一个将 children 传递到 <AliveScope /> 的动作,故真实内容的渲染会相较于正常情况慢一拍,将会对严格依赖生命周期顺序的功能造成一定影响,获取组件ref时可能会获取不到,如下面代码:刷新页面后useEffect中并未拿到Test的ref

import KeepAlive, {useActivate, useUnactivate} from "react-activation";
import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from "react";
import {useNavigate} from "react-router-dom";

const _Test = (props,ref)=>{
    useImperativeHandle(ref,()=>({
        onClick:()=>{
            console.log(1)
        }
    }))
    return <>test组件</>
};
const Test = forwardRef(_Test);

const Home = () => {
    const navigate = useNavigate();
    let [count, setCount] = useState(0);
    let testRef = useRef();
    useEffect(() => {
        console.log(testRef.current)
    }, []);

    useActivate(() => {
        console.log('组件已激活')
    })
    useUnactivate(() => {
        console.log('组件已缓存')
    })
    const onCountChange = ()=>{
        count++;
        console.log(`count值:${count}`)
        setCount(count)
    }

    const goRouter = ()=>{
        navigate('/list')
    }

    return (<>
        <button onClick={onCountChange}>count改变</button>
        <button onClick={goRouter}>跳转list</button>
        <div>count值:{count}</div>
        <KeepAlive>
            <Test ref={testRef}/>
        </KeepAlive>
    </>)
}

export default Home;

在这里插入图片描述

  • 函数组件解决办法使用定时器延时获取ref
import KeepAlive, {useActivate, useUnactivate} from "react-activation";
import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from "react";
import {useNavigate} from "react-router-dom";

const _Test = (props,ref)=>{
    useImperativeHandle(ref,()=>({
        onClick:()=>{
            console.log(1)
        }
    }))
    return <>test组件</>
};
const Test = forwardRef(_Test);

const Home = () => {
    const navigate = useNavigate();
    let [count, setCount] = useState(0);
    let testRef = useRef();
    useEffect(() => {
        setTimeout(()=>{
            console.log(testRef.current)
        },30)
    }, []);

    useActivate(() => {
        console.log('组件已激活')
    })
    useUnactivate(() => {
        console.log('组件已缓存')
    })
    const onCountChange = ()=>{
        count++;
        console.log(`count值:${count}`)
        setCount(count)
    }

    const goRouter = ()=>{
        navigate('/list')
    }

    return (<>
        <button onClick={onCountChange}>count改变</button>
        <button onClick={goRouter}>跳转list</button>
        <div>count值:{count}</div>
        <KeepAlive>
            <Test ref={testRef}/>
        </KeepAlive>
    </>)
}

export default Home;

在这里插入图片描述

  • class组件解决方案可采用@withActivation装饰器
@withActivation
class Test extends Component {
  componentDidMount() {
    console.log(this.outside) // will log <div /> instance
    console.log(this.inside) // will log <div /> instance
  }

  render() {
    return (
      <div>
        <div
          ref={ref => {
            this.outside = ref
          }}
        >
          Outside KeepAlive
        </div>
        <KeepAlive>
          <div
            ref={ref => {
              this.inside = ref
            }}
          >
            Inside KeepAlive
          </div>
        </KeepAlive>
      </div>
    )
  }
}

2.官方还介绍到对 Context 的破坏性影响、对依赖于 React 层级的功能造成影响,我使用的react版本是V18.2.0、react-activation版本是V0.12.4,暂时没遇到,有遇到的伙伴可查看git文档:https://github.com/CJY0208/react-activation/blob/HEAD/README_CN.md

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/509311.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Bun 1.1 发布,全面支持 Windows 系统

4 月 2 日&#xff0c;Jarred Sumner 宣布 Bun 1.1 正式推出。Bun 是一个快速、一体化的工具包&#xff0c;用于运行、构建、测试和调试 JavaScript 和 TypeScript&#xff0c;从单个脚本到全栈应用程序。如果您是 Bun 的新手&#xff0c;可以在 Bun 1.0 博客文章中了解更多信息…

Elasticsearch 免费许可证到期问题解决

问题 es日志报错信息&#xff1a;current license is non-compliant for [security] [2024-04-01T03:20:52.96800:00][ERROR][savedobjects-service] [.kibana_alerting_cases] Action failed with security_exceptionRoot causes:security_exception: current license is no…

Spark 起源发展与项目架构说明

文章目录 前言Spark 的起源Spark 是什么速度易用性模块化可扩展性 分析方法的统一Spark SQLSpark MLlibSpark Structured StreamingGraphX Spark的分布式执行Spark driverSparkSessionCluster managerSpark executor部署模式分布式数据和分区 开发的经验Spark 的使用人群与使用…

0基础 三个月掌握C语言(16)

⽂件操作 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据…

成都直播产业园有哪些特色服务

在成都这片热土上&#xff0c;天府锋巢直播产业基地以其特色服务独树一帜&#xff0c;成为了引领直播行业的先锋。 一、天府锋巢直播产业基地的特色服务&#xff0c;首先体现在其完善的产业链整合能力上。 作为西南大型的成都直播产业园区&#xff0c;这里不仅汇聚了众多优秀…

js实现简单的添加移除水印效果

一、实现场景 在做某些内部管理系统时&#xff0c;需求可能要求增加水印&#xff0c;水印内容通常可能是logo或者用户名手机号。实现效果如图&#xff1a; 以下步骤可实现简单添加或者移除水印&#xff0c;并且可以自定义样式、旋转角度等。 二、实现方式 1、先新建一个js…

网络套接字补充——TCP网络编程

六、TCP网络编程 6.1IP地址字符串和整数之间的转换接口 //字符串转整数接口 #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int inet_aton(const char *cp, struct in_addr *inp); int inet_pton(int af, const char *strptr, …

Go微服务实战——服务治理(负载均衡,请求重试,服务熔断,服务降级)

负载均衡 在微服务架构中各个服务都是独立部署、可独立扩展和管理的。在上一节Go微服务实战——服务的注册与获取&#xff08;nacos做服务注册中心&#xff09;将所有的服务注册到注册中心&#xff0c;供其他服务使用。 这是对于整个系统的层面&#xff0c;对于单个服务来说&…

Linux:运营商在网络中扮演的角色

文章目录 ip目前的问题ip目前的几种解决方案私有ipVS公有ip运营商再谈ip划分运营商的角度看ip 本篇总结的是运营商在网络中扮演的角色 ip目前的问题 在目前看来&#xff0c;ip最大的问题是ip号不够用了&#xff0c;那这个问题如何解决呢&#xff1f; 在之前的内容中有子网掩…

什么是智慧公厕?智慧旅游下的智慧公厕功能和特点

智慧旅游下的智慧公厕功能和特点&#xff1f;智慧旅游是景区、公园、游乐场、文化场馆等领域的一种信息化解决方案&#xff0c;智慧公厕是智慧旅游极为重要的一部分&#xff0c;能大大提升游客满意度。智慧公厕采用物联网、互联网、大数据、云计算等技术&#xff0c;实现旅游景…

RPM与YUM

目录 rpm包的管理 介绍 rpm包的简单查询指令 rpm包名基本格式 rpm包的其他查询指令: 卸载rpm包 yum 介绍 rpm包的管理 介绍 rpm用于互联网下载包的打包及安装工具,它包含在某些Linux分发版中.它生成具有.RPM扩展名的文件.RPM是RedHat Package Manager(RedHat)软件包管…

SDWebImage源码解析---疑难问题解答

SDWebImage的简单流程图&#xff1a; 上图大致流程是对的&#xff0c;有几个没写到的地方&#xff1a; 加载沙盒中对应的图片后&#xff0c;不仅要显示&#xff0c;而且要把图片缓存到内存中下载完毕后&#xff0c;有一个异步解码的过程&#xff0c;没体现出来 网上有大佬做了…

修改nuxtjs项目中的浏览器图标步骤

处理步骤&#xff1a; 打开配置页面 使用el-upload 上传图片到后台 后台把图片转为ico&#xff0c;返回图标路径 配置页面修改本页面预览图&#xff0c;点击保存&#xff0c;修改的数据库。 通知nuxt布局页面&#xff0c;修改head节点中的图标属性&#xff0c;…

智慧酒店(二):AI智能分析网关V4视频分析技术在酒店管理中的应用

一、人工智能技术如何应用在酒店管理中&#xff1f; 随着科技的飞速发展&#xff0c;人工智能技术已经逐渐渗透到我们生活的方方面面&#xff0c;其中&#xff0c;酒店管理行业便是其应用的重要领域之一。人工智能技术以其高效、精准的特点&#xff0c;为酒店管理带来了革命性…

基于java的智能停车场管理系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

文件管理原理

文章目录 1)一个文件&#xff0c;它是文件内容和文件属性的集合 文件文件属性文件内容 文件属性 文件内容 2)文件分为打开的文件和未打开的文件 3)打开的文件是谁打开的&#xff1f; 由进程打开&#xff01;而研究一个被打开的进程本质就是研究进程和文件的关系。 而被打开的…

vue快速入门(二)安装vue调试插件

教程很详细&#xff0c;直接上过程 上一篇 新增内容 在国内网站下载谷歌插件安装插件 点击跳转极简插件 此处我们以Chrome浏览器为例 到这里我们就成功安装了插件 使用上一篇博客的代码在浏览器F12调试一下 这样就可以使用了&#xff01;&#xff01;&#xff01;

依赖倒转原则

1.1 MM请求电脑 MM电脑坏了&#xff0c;需要修电脑&#xff0c;是因为每次打开QQ,一玩游戏&#xff0c;机器就死了。出来蓝底白字的一堆莫名奇妙的英文。蓝屏死机了&#xff0c;估计内存有问题。 1.2 电话遥控修电脑 遥控修理电脑&#xff0c;打开内存条&#xff0c;两根内存…

Python学习从0到1 day20 第二阶段 面向对象 ② 封装

缘分 朝生暮死犹如露水 —— 24.4.1 学习目标&#xff1a; 1.理解封装的概念 2.掌握私有成员的使用 一、面向对象三大特性&#xff1a; 面向对象编程&#xff0c;是许多编程语言都支持的一种编程思想 简单理解是&#xff1a;基于模板&#xff08;类&#xff09;去创建实体&…

免费分享一套SpringBoot+Vue健身房管理系统,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue健身房管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue健身房管理系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue健身房管理系统 Java毕业设计项目来自互联…