设计清晰易懂
让 UI 框架的运作一目了然。
Glory 让应用模型保持显式:语义值描述界面,Owner 管理生命周期,宿主决定如何将语义呈现为像素。
✓
使用手写 Rust 构建器描述界面,无需模板编译器。
✓
构建一次,再发送类型化补丁,无需比较虚拟树。
✓
让状态与订阅始终依附于显式的 Owner 生命周期。
✓
在 Web、SSR 和原生渲染宿主间共享组件。
✓
打开窗口前,先在无界面测试中检查同一套语义模型。
从状态到语义
小巧组合,精确更新。
Cage 拥有可变状态,派生标签追踪该状态,按钮发出语义 Activate 事件。整个组件无需重新渲染。
counter.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use glory::prelude::*;
pub fn counter() -> impl Widget {
widget(|scope| {
let count = scope.cage(0_i32);
let label = count.map(|n| format!("Clicks: {n}"));
row().fill((
text().content(label),
button()
.label("Add one")
.on(activate, move |_| {
count.revise(|n| *n += 1)
}),
))
.show_in(scope)
})
}●
●
●
localhost:8796
真实运行的 GLORY 组件
一个小巧、真实的计数器
由 Glory 自己的 button、text、view 和响应式 Cage 构建。
点击次数:0
同一份 Widget 实现可用于无界面测试、浏览器宿主、SSR 快照和原生窗口。
由宿主决定如何渲染
一棵组件树,多种宿主。
Glory 将界面的含义与平台的呈现方式分开。选择静态 HTML、水合后的 WebAssembly 或原生 Blitz 渲染,无需重写组件。
hydrate.rs
1
2
3
4
5
6
7
// Serialize a versioned semantic snapshot.
let snapshot = glory::ssr::snapshot(counter())?;
let html = format!("<main id=\"app\">{}</main>", snapshot.html);
// Adopt that exact HTML in the browser.
let app = glory::web::hydrate(root, counter())?;
// Keep the WebApp alive.