跳到主要内容

运行时与更新

MountAsync

MountAsync 会遍历元素树、分配 NodeHandle、写入 CreateElement、属性、样式、 文本、监听器以及最终的 SetRoot opcode,并把 frame 发送到 WebKitGTK renderer。

await using var host = RenderHostFactory.CreateWebKitGtk();
var app = App.Create(host);

var root = new Div();
root.Children.Add(new Button("Save"));

await app.MountAsync(root, cancellationToken);
await host.RunAsync(cancellationToken);

Update

UpdateUpdateAsync 提交 imperative DOM update transaction。事务会复用 已挂载元素的 handle,并在一个 frame 中写入文本、属性、样式、子节点或监听器变更。

await app.UpdateAsync(tx => tx
.SetText(button, "Saved")
.SetAttr(button, "class", "primary")
.SetStyle(button, StylePropId.FontSize, 16), cancellationToken);

HTML / CSS Load

WebKitGTK host 可以直接加载 HTML 和 CSS:

await using var host = RenderHostFactory.CreateWebKitGtk();

await host.LoadHtmlAsync("<main><h1>Hello</h1></main>");
await host.LoadCssAsync("h1 { color: rgb(1, 2, 3); }");

LoadHtmlAsync 默认不允许 HTML 自带 JavaScript。加载前会通过浏览器 DOM parser 解析并清理 <script>iframeobjectembedmeta[http-equiv]、 inline event handler、srcdocjavascript: URL,然后再替换当前 document 的 head/body。框架内部的 shim 仍然可以继续工作。

LoadCssAsync(css) 会写入默认 stylesheet。LoadCssAsync(css, styleId) 会写入 或替换同名 stylesheet,适合主题或热更新样式。

子节点 transaction 支持创建新子树、插入、移动、分离和销毁:

var item = new Li("New");

app.Update(tx => tx
.InsertBefore(list, item, before)
.MoveBefore(list, item, null)
.RemoveChild(list, oldItem)
.RemoveNode(item));

RemoveChild 只把子树从父节点分离,节点 handle 仍可再次插入。RemoveNode 会 销毁 renderer 侧节点、释放 arena row,并清理该子树的 listener binding。

事件监听器

监听器通过 ListenerRegistry 映射到 wire token。renderer 只回传 token 和事件 payload,C# 侧再按 token、event id 和 node id 确认 binding 后解析并调用对应 delegate。

Action handler = () => Console.WriteLine("clicked");

app.Update(tx => tx.AddListener(button, eventId: 1, handler));
app.Update(tx => tx.RemoveListener(button, eventId: 1, handler));

RemoveListener 要求传入之前注册过的同一个 delegate identity;未注册的移除会 抛出异常,避免向 renderer 发送无意义 token。

同一个 delegate 可以绑定到多个节点;移除其中一个节点的监听器不会影响其他节点。 销毁节点或 dispose app 时,C# registry 会清理对应 binding,renderer shim 也会在 RemoveNode 时清理 listener 表。

Dispose

UltimateUiApp 实现 IAsyncDisposable。Dispose 会取消 inbound 事件订阅、清空 listener registry,并释放绑定的 IRenderHostIDomBackend