Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
T treasure
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 13
    • Issues 13
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • External wiki
    • External wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • FE
  • treasure
  • Issues
  • #181

Closed
Open
Created Aug 24, 2023 by chenyu@CubiDeveloper

react 项目使用 keepalive 抽屉弹窗卡死问题

问题:react 项目当页面使用 keepalive后,在当前页面打开弹窗抽屉等组件时,点击后退页面。会出现背后页面后退,弹窗抽屉等组件未关闭,且关闭不了的现象。 react项目使用keepalive+抽屉问题

react-keep-alive 原理

在 KeepAlive 组件中,通过 AliveScope 高阶组件获取到 keep 函数。在组件的初始化阶段,调用 init 方法,将组件的 id、children 和 keep 函数传递进去。在 init 方法中,调用 keep 函数,并使用 Promise 的 resolve 回调函数将真实的组件内容添加到 placeholder(占位符)div 节点中。 最后,在 KeepAlive 组件中,通过 ref 获取到 placeholder 节点,并将其保存为实例属性。这样,当 KeepAlive 组件再次渲染时,placeholder 节点已经包含了之前缓存的真实组件内容,所以实际上不再需要重新渲染组件,只需将 placeholder 节点直接添加到 DOM 树中。 image 简单概括:

  1. AliveScope组件拿到 KeepAlive组件传来的虚拟 dom 进行渲染,这样在 fiber 树上会表示这个组件已经被渲染了;
  2. 渲染后AliveScope组件将这个 dom 传给KeepAlive组件,KeepAlive组件获取 dom 后将其插入自己渲染的 dom 里;
  3. 这样就会导致,AliveScope组件渲染了 dom,并且有这个 dom 的 fiber,享受AliveScope组件的生命周期,但是渲染确实按照KeepAlive组件的渲染逻辑走,当KeepAlive组件卸载时,fiber 会 commit 掉子组件的 dom。
  4. 当KeepAlive组件重新显示时,会调用 AliveScope 方法,重新获取 KeepAlive 组件已经渲染的 dom。(也有说是缓存在 fiber 树上)

分析原因:react-router在对路由匹配时,不匹配的就直接卸载了。而react 的 keepalive 组件使用的原理是将 dom 缓存在AliveScope 组件中,当路由变化时页面 dom 被缓存在 fiber 树上而未被卸载,导致抽屉组件不会被卸载。

解决方案

  1. 将 drawer/modal 等组件挂载在当前页面上 image 将 drawer 挂载在父级 div 上,能解决路有变化隐藏 drawer/modal,且不会影响层级(包括微应用)。但体验会有些不好,会有闪屏情况出现。 keepalive缓存drawer和modal后闪屏记录

  2. 删除 KeepAlive

该方案需要与产品确定,目前已咨询童格,暂时无法确定。如需修改切记与产品同步。

因为目前详情交互改为抽屉打开,关闭不会影响列表页筛选和分页,顾不需要KeepAlive功能缓存页面信息,可逐步删除 KeepAlive image 目前出现的资源微服务与 pms-react-pc应用 KeepAlive组件多数在 app.tsx 里包裹,可直接删除。(注意:微应用代码有两处 KeepAlive需要删除)

Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking