creamidea / creamidea.github.com

冰糖火箭筒&&蜂蜜甜甜圈
https://creamidea.github.io/
4 stars 4 forks source link

JSX 是声明式“语言” #37

Open creamidea opened 2 years ago

creamidea commented 2 years ago

最近,碰到一个更新问题,让我对 JSX 是声明式的有了更深的理解。问题后续有空详细解释,现在简单说一下。

问题场景是,如下 JSX 描述的 UI

<Layout>
  <Tab>
    <TabItem><Table /></TabItem>
    <TabItem><Table /></TabItem>
  </Tab>
</Layout>

在 Layout 这个组件内部会 clone children,在 clone 前会找到 Table,并改变其属性,然后 clone。问题在于,改变属性并不能使 Table 重新渲染,「按理」来说,如果 Table 属性变化,会在 reconciler 阶段被识别为 Update,在 commit 阶段进行「渲染」。为什么?

因为这里的 Tab 组件也会处理其 children,如果内部只对第一次渲染处理,所有后续渲染全部 return 之前的 children(这个例子很极端,只是让大家更好的理解)。那么你再怎么处理 Table,也不会使 Table 被重新渲染(因为在 React 看来,Tab 后续的 children 都没有变化)。这里的 Tab JSX 只是描述了这样的 UI,也就是所谓的声明式,Tab 内部有一套自己的处理方式,处理完成的结果才会给 React 去 reconciler,而不是你在 Layout 内部处理的之后的 children。React 只会相应 Layout 第一层,比如这里的 Tab。

~这里使用的 Tab 来自 fusion 组件库,这行代码,类似做了一次缓存(返回了空对象),导致如果 Tab 标签页不进行切换,那么就没办法更新其 children,也就是上面说的 Table。~