Rust in Everything
基于 dioxus 0.7.10

rsx 与组件

这一部分讲用户写下的两样东西:rsx! 和组件函数。源码分在三处:packages/rsx/src(约 5.7k 行,rsx! 的解析和代码生成,template_body.rs、assign_dyn_ids.rs、element.rs、attribute.rs、ifmt.rs)、packages/core-macro/src(约 3.3k 行,#[component] 和 Props derive)、packages/core/src 里的 nodes.rs、properties.rs、render_error.rs(运行期的数据结构)。

dioxus 和 React 一样每次更新都整个重跑组件函数、得到一棵新的虚拟树,区别在 rsx! 在编译期就把树里不会变的部分切出去,印成一个 static 的模板;组件每次只新建动态部分。这一部分讲到组件函数返回一个 VNode 为止,新旧两个 VNode 怎么比、指令怎么发出去,在 03 VirtualDom 内核。

  1. rsx! 展开成什么:rsx! 解析成 CallBody,根、组件 children、for 循环体、if 的每个分支各是一个模板;只有不含洞的字符串字面量能进模板,整数、布尔、const、花括号表达式都是动态的;动态部分按深度优先编号,路径的第一个数是根的下标;release 下是 static Template,debug 下路径在运行期算、每个洞多格式化一次,给热重载用。
  2. Template 与 VNode:VNode 是 16 字节的 Rc 加挂载号,相等只比指针;Template 是三个静态切片,release 按指针比、debug 按值比;DynamicNode 的四种变体,AttributeValue 的七种值;Element 就是 Result<VNode, RenderError>;IntoDynNode 决定什么能放进 {}。
  3. #[component] 与 Props:#[component] 生成 Props 结构体和类型状态 builder;memoize 相等就跳过子组件;实验数出每种 props 的重跑次数:普通值按值比,闭包和 children 按指针比、每次都重跑,ReadSignal 跳过子组件但通知订阅者。
flowchart TB
  src["rsx 宏调用"] --> tpl["static Template"]
  src --> dyn["动态部分 按序号"]
  tpl --> vnode["VNode"]
  dyn --> vnode
  comp["component 函数"] --> props["Props 与 builder"]
  props --> vcomp["DynamicNode Component"]
  vcomp --> dyn
  vnode --> diffnode["03 diff"]
  props --> memo["memoize"]
  memo --> diffnode

💬 关联讨论

发起讨论
加载中...