React-Route6实现keep-alive效果

目录
  • 一、基于react-route6  useOutlet实现
  • 二、代码呈现
  • 代码分析
    • isKeepPath
    • useKeepOutlets
    • location
    • element
    • useContext<any>(KeepAliveContext)
    • isKeep
    • Object.entries
    • key
    • hidden
    • matchPath(location.pathname, pathname)}
    • KeepAliveLayout
    • FC
    • keepElements
    • dropByCacheKey
    • other
    • Provider
  • 三、使用

一、基于react-route6  useOutlet实现

二、代码呈现

import React, { useRef, createContext, useContext } from 'react'
import { useOutlet, useLocation, matchPath } from 'react-router-dom'
import type { FC } from 'react'
//在组件外部建立一个Context
export const KeepAliveContext = createContext<KeepAliveLayoutProps>({ keepalive: [], keepElements: {} })

//给予页面缓存设置条件判断
const isKeepPath = (aliveList: any[], path: string) => {
  let isKeep = false
  aliveList.map(item => {
    if (item === path) {
      isKeep = true
    }
    if (item instanceof RegExp && item.test(path)) {
      isKeep = true
    }
  })
  return isKeep
}
//判断当前页面是否已缓存,是则控制hidden开关显示 ,不是则正常渲染
export function useKeepOutlets() {
  const location = useLocation()
  const element = useOutlet()
  const { keepElements, keepalive } = useContext<any>(KeepAliveContext)
  const isKeep = isKeepPath(keepalive, location.pathname)
  if (isKeep) {
    keepElements.current[location.pathname] = element
  }
  //标签的显示与隐藏
  return <> {
    Object.entries(keepElements.current).map(([pathname, element]: any) => (
      <div key={pathname}
      style={{ height: '100%', width: '100%', position: 'relative', overflow: 'hidden auto' }}       className="rumtime-keep-alive-layout"
      hidden={!matchPath(location.pathname, pathname)}>
        {element}
      </div>
    ))
  }
    <div hidden={isKeep} style={{ height: '100%', width: '100%', position: 'relative', overflow: 'hidden auto' }} className="rumtime-keep-alive-layout-no">
      {!isKeep && element}
    </div>
  </>
}
//设置公共组件类型
interface KeepAliveLayoutProps {
  keepalive: any[]
  keepElements?: any
  dropByCacheKey?: (path: string) => void
}
//封装公共组件
const KeepAliveLayout: FC<KeepAliveLayoutProps> = (props) => {
  const { keepalive, ...other } = props
  const keepElements = React.useRef<any>({})
  function dropByCacheKey(path: string) {
    keepElements.current[path] = null
   } return (<KeepAliveContext.Provider
    value={{ keepalive, keepElements, dropByCacheKey }}
     {...other} />)
    }

  export default KeepAliveLayout

代码分析

isKeepPath

配置 keepalive 支持字符串和正则,通过它来判断,当前页面是否需要状态保持,因为如果整个项目的页面都保持状态的话,对性能是很大的消耗

参数1为可缓存路径或正则表达式组成的数组,参数2为当前路径。

若当前路径在已缓存路径数组中或其路径符合正则表达式则isKeep为true,反之为false

useKeepOutlets

通过判断当前页面是否是需要保持的页面来对页面 DOM 做一个 hidden 显隐开关。

需要注意的是所有被指定状态保持的页面在首次渲染之后,都会被挂载在页面 DOM 树上,仅仅是使用 !matchPath(location.pathname, pathname) 控制显隐。

而没有被指定状态保持的页面,则是使用 {!isKeep && element} 控制,走 React 组件正常的生命周期。

location

当前路径信息

element

获取当前路由组件即当前配置下的嵌套路由组件

useContext<any>(KeepAliveContext)

通过useContext()钩子函数获取Context对象中的属性,已便于组件之间共享状态

isKeep

将当前路径利用页面缓存设置条件判断是否为已缓存路径,若符合条件,isKeep为true,则将keepElements Ref中以当前组件路径名为属性名的属性绑定当前路由组件

Object.entries

描述:Object.entries()返回一个数组,其元素是与直接在object上找到的可枚举属性键值对相对应的数组。属性的顺序与通过手动循环对象的属性值所给出的顺序相同。

可枚举:枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值

参数:可以返回其可枚举属性的键值对的对象

返回值:给定对象自身可枚举属性的键值对数组

key

保持 key 不变,就不会触发 React 的重绘

hidden

控制显示与隐藏开关

matchPath(location.pathname, pathname)}

所有被指定状态保持的页面在首次渲染之后,都会被挂载在页面 DOM 树上,仅仅是使用!matchPath(location.pathname, pathname) 控制显示隐藏。

//matchPath:参数1为当前路径,参数2为缓存路径,确定当前路由路径是否与缓存路径匹配

而没有被指定状态保持的页面,则是使用 {!isKeep && element} 控制,走 React 组件正常的生命周期

KeepAliveLayout

为封装后暴露的组件

FC

React.FC是函数式组件,是在TypeScript下使用的一个泛型,全称为React.FunctionComponentReact.FC<> 可检测指定属性类型

keepElements

使用 React.useRef<any>({}) 来做页面数据保存的节点,是因为我们的上下文不被重新渲染的话 keepElements 就不会被重置,相当于 key

dropByCacheKey

dropByCacheKey为清除缓存的函数,通过控制当前组件的ref来销毁组件

other

const { keepalive, ...other } = props中...other为其他配置,这里我们直接遍历继承即可

Provider

(<KeepAliveContext.Provider value={{ keepalive, keepElements, dropByCacheKey }} {...other} />)

原理:

每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。

Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。

当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染

三、使用

import KeepAliveLayout, { useKeepOutlets, KeepAliveContext }from'@/components/KeepAliveLayout'
import { useLocation } from 'react-router-dom'
import React, { useState, useContext } from 'react'

// 使用KeepAliveLayout中的useKeepOutlets获取当前渲染的页面内容
const Layout = () => {
    const element = useKeepOutlets()
    return (
        {element}
    )
}
// 使用 KeepAliveLayout 包裹上下文
const App = () => {
    return (
        <KeepAliveLayout keepalive={[/./]}>//不可能组件都缓存吧所以需要设置缓存条件,可传可缓存的路径或正则表达式
            // App
        </KeepAliveLayout>
    );
}
// 使用 useContext 获取 dropByCacheKey 清除缓存
const Home = () => {
    const { dropByCacheKey } = useContext<any>(KeepAliveContext);
    const { pathname } = useLocation();
    return (
       <button onClick={() => dropByCacheKey(pathname)}>清除缓存</button>
    )
}

到此这篇关于React-Route6实现keep-alive效果的文章就介绍到这了,更多相关React-Route6 keep-alive 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • React-Router6版本的更新引起的路由用法变化

    目录 用法变化 替换为 嵌套路由 重定向 路由跳转 路由传参 search传参 动态路由传参 其他 总结 React Router应该是React生态系统中最受欢迎的库了,npm周下载量达600w+,github也有45.2k的加星,足以说明它是一款非常优秀的库,作为React社区重要的库,它经历了多次迭代和重大更改,就在上个月,更是迎来了一个大的正式版更新6.x,当前最新为6.0.2,相对比于之前的5.x版本做出了较大改变,不管从用法还是从性能上都有了明显的提升,本文也将用新老版本对比的方式让

  • react-router-dom v6 通过outlet实现keepAlive 功能的实现

    本文主要介绍了react-router-dom v6 通过outlet实现keepAlive 功能的实现,具体如下: keepAlive代码: import React, { useRef, useEffect, useReducer, useMemo, memo } from 'react' import { TransitionGroup, CSSTransition } from 'react-transition-group' import { useLocation } from 'r

  • 详解react-router-dom v6版本基本使用介绍

    目录 Routes Route Navigate NavLink useRoutes 嵌套路由 路由传参 编程式导航 Routes 代替Switch组件,不会向下匹配 用来包裹Route Route 必须被Routes组件包裹 component属性变成element caseSensitive 路径大小写敏感属性,默认是不敏感(访问/about = /ABOUT) index 与path属性是互斥的,index表示为当前路由的根 可以用作layout组件,不写element属性,写了要与 Ou

  • 浅谈React-router v6 实现登录验证流程

    目录 封装 Context 包裹容器 封装 Layout 父级容器 开发 Login 模块 开发 Protected 包裹容器 App 入口文件 此示例演示了一个包含三个页面的简单登录流程:公共页面.受保护页面和登录页面. 为了查看受保护的页面,你必须先登录.首先,访问公共页面. 然后,访问受保护的页面. 你尚未登录,因此你将被重定向到登录页面. 登录后,你将被重定向回受保护的页面. 封装 Context 包裹容器 首先封装AuthProvider组件,利用Context特性共享那些对于一个组件

  • react-router-dom V6的配置使用实践

    目录 一.关于书写方面 二.路由的嵌套方面优化 三.关于路由的灵活配置化 四.关于路由鉴权方面 最近在搭建PC项目的React框架,涉及到React Router,开发同学有时就需要去尝试点新的东西,在开发过程中才不会枯燥的,基于这个理念推动,就在搭建的时候用V6的版本开始了(虽然只是个新版本,也不算啥新东西)...... V6的版本相对于V5,做了很多的优化,有书写方面的.路由的嵌套.路由配置化.鉴权方面等等,下面就简单的介绍下如何使用 一.关于书写方面 路由注册的时候由的Switch改为了R

  • react-router-domV6版本的路由和嵌套路由写法详解

    目录 1-单级路由 2-嵌套路由(about路径进行嵌套) ReactRouterv6使用路由嵌套和重定向 1 - 单级路由 <NavLink to="/home">Home</NavLink> <NavLink to="/about">about</NavLink> <Routes>   <Route path='/home' element={<Home/>}/>   <R

  • React + Threejs + Swiper 实现全景图效果的完整代码

      咱先看看全景图实现效果:展示地址   截图:   体验了一下是不是感觉周围环境转了一圈,感觉世界是圆的?

  • React+ts实现二级联动效果

    本文实例为大家分享了React+ts实现二级联动效果的具体代码,供大家参考,具体内容如下 .tsx文件 import { Component, createRef} from 'react' import './index.less' interface State { top: any ButtonList: Button[] ContentList: Content[] ButtonIndex: number } interface Button { id: string text: str

  • Three.js+React实现3D文字悬浮效果

    目录 背景 效果 实现 资源引入 DOM结构 设置状态 网格背景 场景初始化 创建材质 创建文字模型 创建几何体模型 鼠标事件监听 背景色切换 后期渲染 动画 缩放适配 双击全屏 总结 背景 在 Three.js Journey 课程示例中,提供了一个使用 Three.js 内置方法实现的 3D 文字悬浮效果的例子,本文使用 React + Three.js 技术栈,参照示例实现类似的效果.本文中涉及到的知识点主要包括:CSS 网格背景.MeshNormalMaterial 法向材质.FontL

  • React实现轮播图效果

    本文实例为大家分享了React实现轮播图效果的具体代码,供大家参考,具体内容如下 效果: 轮播功能用到了react-slick组件,安装: npm install react-slick --save npm install slick-carousel 安装完后需要在使用轮播图的页面上导入css文件: import Slider from 'react-slick'; import 'slick-carousel/slick/slick.css'; import 'slick-carousel

  • React实现卡片拖拽效果流程详解

    前提摘要: 学习宋一玮 React 新版本 + 函数组件 &Hooks 优先 开篇就是函数组件+Hooks 实现的效果如下: 学到第11篇了 照葫芦画瓢,不过老师在讲解的过程中没有考虑拖拽目标项边界问题,我稍微处理了下这样就实现拖拽流畅了 下面就是主要的代码了,实现拖拽(src/App.js): 核心在于标记当前项,来源项,目标项,并且在拖拽完成时对数据处理,更新每一组数据(useState): /** @jsxImportSource @emotion/react */ // 上面代码是使用e

  • react native仿微信PopupWindow效果的实例代码

    在原生APP开发中,相信很多开发者都会见到这种场景:点击右上角更多的选项,弹出一个更多界面供用户选择.这种控件在原生开发中Android可以用PopupWindow实现,在iOS中可以用CMPopTipView,也可以自己写一个View实现.其类似的效果如下图所示: 实现思路分析: 要实现上面的视图,有很多种实现方式.前面的文章说过,要实现弹框相关的可以用React Native 提供的 Modal组件(Modal组件),使用Modal组件可以实现我们原生开发中的大多数效果. 要实现下拉三角,可

  • react基于react-slick实现多图轮播效果

    目录 写在前面: 一.进入官网查看文档(Docs) 二.安装插件(Quick Start) 三.范例使用(Examples) 1.直接copy代码: 2.实现结果: 3.引入样式: 4.还是报错? 5.运行成功! 实现结果: 总结 写在前面: 目前在项目中有轮播图需求,但是antd组件不能实现多张图片的轮播(或许是我没找到相应方法) 最后找到react-slick插件,能实现想要的效果 一.进入官网查看文档(Docs) react-slick官网 二.安装插件(Quick Start) //np

  • React Native仿美团下拉菜单的实例代码

    本文介绍了React Native仿美团下拉菜单的实例代码,最近也在学习React Native,顺便分享给大家 在很多产品中都会涉及到下拉菜单选择功能,用的最好的当属美团了,其效果如下: 要实现上面的效果,在原生中比较好做,直接使用PopWindow组件即可.如果使用React Native开发上面的效果,需要注意几个问题: 1. 在下拉的时候有动画过度效果: 2.下拉菜单出现后点击菜单项,菜单项可选择,并触发对应的事件: 3.下拉菜单中的项目可以配置: 要实现弹框效果,我们马上回想到使用Mo

  • React实现二级联动的方法

    本文实例为大家分享了React实现二级联动的具体代码,供大家参考,具体内容如下 实现效果: 普通h5页,图片我进行了裁剪,把用户那部分删掉了,不过也不影响说明 大体思路就是把数据接口从页面传给组件,交互在组件内执行后,通过onTimeChange将选择的数据结果返回给页面,然后展示到页面上. 我用Taro写的,语法和react一样. 小程序效果 好久以前的一个方法,给大家发下实现代码: 1.页面里有一个选择时间的弹框模块 {this.state.isToggleOn && ( <Pa

  • react中的watch监视属性-useEffect介绍

    目录 react的watch监视属性-useEffect useEffect使用指南 最基本的使用 响应更新 如何处理Loading和Error 处理表单 自定义hooks 使用useReducer整合逻辑 取消数据请求 react的watch监视属性-useEffect 在vue中可以使用watch属性,去监视一个值,当这个值进行变化的时候就去执行一些操作.在react是没有这个属性的,但是它也一样可以达到相同的效果,那么接下来看看它是怎么实现的呢? 在react中实现监听效果有一个比较简单的

随机推荐