Skip to content

Commit

Permalink
2024年 4月 4日 星期四 01时02分20秒 CST
Browse files Browse the repository at this point in the history
  • Loading branch information
Liubasara committed Apr 3, 2024
1 parent f026bed commit 6cba64b
Showing 1 changed file with 24 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: 几小点说明为何KeepAlive组件不是最终解决方案
title: "几小点说明为何KeepAlive组件不是最终解决方案"
tags: ["技术", "瞎折腾"]
categories: 瞎折腾
info: "清明时节雨纷纷,组件缓存欲断魂"
time: 2024/4/4
desc: 几小点说明为何KeepAlive组件不是最终解决方案
keywords: ['前端', 'typescript', 'javascript']
---

# 几小点说明为何KeepAlive组件不是最终解决方案

大多数框架都提供了基于组件维度 KeepAlive 的缓存机制,然而,前端使用`<keep-alive></keep-alive>`组件来进行性能优化永远只能是暂时的,最简单的道理就是,UI 的渲染成本已经越来越低了,何况还有 VDOM,用 display:none 属性保存 DOM 结构完全是一种增加心智负担且没有必要的行为。大多数场景下,前端想要缓存的永远是组件中的数据。

但是如果是一个用合理的 Headless 架构构建出来的应用程序,它的状态原本就是独立在外层,一层层业务层像洋葱一样把 UI 组件包裹住的,只要页面不关闭,外层的业务层所代表的组件根本不会销毁,所以根本不需要 keep-alive 组件。一旦 UI 重新挂载需要重新加载数据,完全可以让业务层下发这个刷新的能力,让 UI 组件在挂载的生命周期触发即可。

这个结论同样也能支持反例,假如使用 keepAlive 组件来包裹 A 组件和 B 组件,那么只要业务够复杂,就一定会遇到 A 组件中的一个小组件 Aa 和 B 组件中的一个小组件 Ba 同属于同一个业务的情况。此时如果业务需要 A 组件和 B 组件不被缓存,但是每次渲染的时候 Aa 和 Ba 又不能重新渲染,在不使用 Store 的情况下,KeepAlive 组件只能通过一些很丑陋的 Include 和 Exclude 来穿透监听,完全违背了职责分离原则。

而如果使用 Store,那么其实还是抛弃了 KeepAlive 的组件缓存机制,走了上面所说的数据与 UI 对应的机制,因为很明显 UI 在这里是经过了两次不同的渲染的。甚至我们说在如今前端框架普遍提供了类似于 inject 和 provide 的时代,Store 的存在也显得没有必要了。因为不同业务之间的 Store 相互引用,很容易让不同的业务之间形成网状的结构,其结果就是状态刷新时牵一发而动全身,难以摸清规律。所以如今我们会更倾向于使用简单的 Provide 和 Inject 来让数据之间形成嵌套式的关系,如果遇到共同的依赖,那就再抽离一层子层同时依赖双方,进行双边逻辑的处理,让整个数据流始终保持在自外向内的洋葱结构中,以便在数据刷新时,能够最小化的刷新对应的业务层。

结论:前端不应该局限于基于组件级别使用 KeepAlive 进行缓存,前端缓存的最终目标一定是基于业务层的状态进行分层缓存。


0 comments on commit 6cba64b

Please sign in to comment.