因为 React 的特点,组件扭转所在父级后会产生 Remount,而在可视化搭建场景存在两个特点:
- 自在、磁贴、流式布局都能够通过拖拽轻松扭转组件父元素。
- 大数据量下组件 Remount 的耗费不容忽视。
联合下面两个特点,拖拽过程中或者松手时不可避免会产生卡顿,这就是咱们这篇文章要解决的问题。
利用 createPortal 解决 Remount 问题
createPortal 能够将 React 实例渲染到任意指定 DOM 上,所以咱们利用这个 API,将组件树的组件打平,但通过 createPortal 生成到嵌套的 DOM 树上,就同时实现了以下两点:
- 在 dom 构造上仍然合乎组件树的嵌套形容。
- 在 React 实例角度,没有嵌套关系。
实现分为三步:
- 遍历组件树,依据组件树嵌套构造生成 createPortal 的指标 dom,咱们权且称为 keepElement,对须要挂载 keepElement 的容器地位生成 dom,称为 keepContainer。对于没有渲染的容器,能够先不挂载 keepElement,而是等到父容器 mount 后再将 keepElement 移过去,前面再开展阐明。
- 遍历组件树,一次性打平渲染所有树中 React 组件实例,并利用 createPortal 挂载到对应的 keepElement 上。
- 当数据流产生变动导致父级变动,或者布局插件拖动扭转父级时,咱们仅利用 dom api 将 keepElement 在不同的 keepContainer 之间挪动,而在 React 实例视角没有产生任何变动。
<img width=500 src=”https://s1.ax1x.com/2023/03/25/ppDLFSO.png”>
协定做到用户无感知
因为实现了 dom 构造与 React 实例构造拆散,因而开启 keepAlive 模式不须要扭转 componentTree
形容,也不会影响任何逻辑性能,咱们只须要标记一下 keepAlive
参数即可开启:
import {createDesigner} from 'designer'
const {Designer, Canvas, useDesigner} = createDesigner()
const App = () => {<Designer keepAlive={true} />
}
渲染减少了额定 dom 嵌套
keepAlive 模式惟一对性能产生的影响是减少了额定 dom 嵌套,别离是 keepContainer 与 keepElement,产生这两层 dom 的起因别离是:
- keepElement: 因为 React 实例 Remount 的作用范畴是该组件本身 return 的所有虚构 dom 最终映射的实在 dom,为了保障 React 映射 dom 与 React 树结构的对应,为了不产生 Remount 就必须要用额定的游离态 dom 作为 createPortal 的挂载节点。
- keepContainer: 因为不仅要晓得组件产生挪动时,应该将 keepElement 挪动到哪个 keepContainer 下,还须要在比方容器代码
return children
地位忽然return null
并复原时,从新构建 keepElement,所以咱们须要监听每一个 keepContainer 生命周期,所以须要额定生成一个 dom。
因而 keepAlive 模式势必会打乱原有利用的 dom 构造,新增的 dom 构造在比方流式布局时可能产生意外的定位谬误,所以 keepAlive 模式尽量与相对定位的布局形式联合。
总结
keepAlive 模式能够在不扭转任何协定、利用代码的状况下,解决跨父级挪动导致的 Remount 问题,但这种设计也会引入新增 dom 构造的问题,只有尽量采纳相对定位的布局策略,就能够防止负面影响。
探讨地址是:精读《可视化搭建 – keepAlive 模式》· Issue #475 · dt-fe/weekly
如果你想参加探讨,请 点击这里,每周都有新的主题,周末或周一公布。前端精读 – 帮你筛选靠谱的内容。
关注 前端精读微信公众号
<img width=200 src=”https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg”>
版权申明:自在转载 - 非商用 - 非衍生 - 放弃署名(创意共享 3.0 许可证)