手写KeepAlive组件

一、React 默认"切换组件就会卸载"

ini 复制代码
{activeTab === 'A'
  ? <Counter name="A" />
  : <OtherCounter name="B" />
}

从 A 切到 B:A 卸载,B 挂载

因为在 React 眼里,这是两棵完全不同的树

二、KeepAlive 真正解决是:

让组件不要被卸载

组件实例始终存在于 Fiber 树里,只是隐藏

三、核心思想:缓存 children(React 元素)

scss 复制代码
if(!cache[activeId]){
  setCache((prev)=>({
    ...prev,
    [activeId]:children,
  }))
}

<Counter name="A" />本质是一个:ReactElement 对象

把这个对象保存起来

四、保存 children 就能"保活组件"

css 复制代码
Object.entries(cache).map(([id,component])=>(
  <div
    key={id}
    style={{display:id === activeId ? 'block' : 'none'}}
  >
    {component}
  </div>
))

只要 component 被渲染过一次:

perl 复制代码
React 创建 Fiber
React 创建真实 DOM
React 建立 state
React 建立 effect

之后再也没有移除它 ,只是:display:none

五、完整 KeepAlive

ini 复制代码
const KeepAlive = ({ activeId, children }) => {
  const [cache, setCache] = useState({});

  useEffect(() => {
    setCache(prev => {
      if (prev[activeId]) return prev;
      return {
        ...prev,
        [activeId]: children,
      };
    });
  }, [activeId, children]);

  return (
    <>
      {Object.entries(cache).map(([id, component]) => (
        <div
          key={id}
          style={{ display: id === activeId ? 'block' : 'none' }}
        >
          {component}
        </div>
      ))}
    </>
  );
};

总结

childrenReactElementReactElement 可以被缓存,只要 ReactElement 一直被 render,组件就不会卸载,KeepAlive 的本质是:结构稳定,样式切换

相关推荐
IT_陈寒2 分钟前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow26 分钟前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林81828 分钟前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang8007828 分钟前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明32 分钟前
第 6 章 组件进阶
前端·vue.js
江华森35 分钟前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端
南青35 分钟前
Vue 3 中后台实战:我踩过的 10 个坑和最佳实践
前端
江华森37 分钟前
HTTPS协议详解——SSL/TLS握手、证书与加密通信
前端
江华森44 分钟前
从一个HTTP请求看网络分层原理:基于华为云ECS的真实抓包实战
前端
江华森1 小时前
TCP协议详解——三次握手、四次挥手与连接状态
前端