1.1 设计理念与哲学
> **核心理念**:独立标记文件(`.rml`)+ 纯 Rust 业务逻辑(`.rml.rs`),对标 WPF XAML 的设计精髓,拥抱 HTML 的语法亲和力。
1.1.1 背景:GPUI 的机遇与挑战
GPUI 是 Zed 编辑器团队开发的**混合即时与保留模式、GPU 加速**的 Rust UI 框架。它提供了高层级的声明式 UI 视图系统——所有 UI 从实现 `Render` trait 的 View 开始,框架在每帧调用 `render` 方法构建 UI 树。GPUI 拥有 Tailwind 风格的样式 API 和 GPU 加速渲染能力,已被证明能够支撑 Zed 这样大规模、高性能的桌面应用。
然而,GPUI 当前的 UI 开发模式存在显著痛点:
// 原生 GPUI 的 UI 构建方式 —— 命令式链式调用
div()
.flex()
.flex_col()
.gap(px(16.0))
.p(px(24.0))
.bg(rgb(0xf5f5f5))
.child(
div()
.text_xl()
.font_weight(FontWeight::BOLD)
.child(Label::new("Hello World"))
)
.child(
div()
.flex()
.gap(px(8.0))
.child(
Button::new("Click me")
.on_click(cx.listener(|this, _ev, cx| {
this.count += 1;
cx.notify();
}))
)
)
**核心问题**:
1. **UI 逻辑深度耦合**:UI 结构与业务逻辑、事件处理交织在同一个 Rust 文件中 2. **代码冗长**:链式调用的嵌套结构难以阅读和维护 3. **设计师无法参与**:UI 代码是 Rust 语法,非工程师无法理解和编辑 4. **缺乏标准化**:没有统一的 UI 标记语言,每个项目各自为政
1.1.2 设计目标
RML 旨在彻底解决上述问题,为 GPUI 带来工业化级别的 UI 开发体验:
| 目标 | 说明 | | ------------- | --------------------------------- | | **关注点彻底分离** | UI 结构(`.rml`)与业务逻辑(`.rml.rs`)完全独立 | | **HTML 语法亲和** | 使用标准 HTML 标签和属性,Web 开发者零学习成本 | | **WPF 级数据绑定** | 支持单向/双向绑定、值转换、命令系统 | | **零运行时开销** | 编译期将 `.rml` 转换为原生 GPUI 渲染代码 | | **设计师友好** | 纯标记语言,可使用任何 XML/HTML 编辑工具 | | **热重载就绪** | 独立文件为运行时监听和热更新提供天然基础 |
1.1.3 三条根本原则
RML 的设计遵循三条根本原则,它们是后续所有语法、API、宏设计的判据。理解这三条原则,就能预测 RML 在任何场景下的行为。
① 声明式优于命令式
> 描述"是什么 UI",而非"如何构建 UI"。
HTML 的 `<div class="flex">` 比 `div().flex()` 更接近人类认知:UI 结构一目了然,而非逐行推导。RML 把所有命令式构建逻辑下沉到编译期,开发者只描述结果。
<!-- RML:描述"是什么" -->
<div class="flex flex-col gap-4 p-6">
<h1>标题</h1>
<button on-click={submit}>提交</button>
</div>
// 原生 GPUI:描述"怎么构建"
div().flex().flex_col().gap(px(16.0)).p(px(24.0))
.child(div().text_xl().child(Label::new("标题")))
.child(Button::new("提交").on_click(cx.listener(|this, _, cx| this.submit(cx))))
② 逻辑与表现彻底分离
> UI 文件不含业务逻辑,逻辑代码不含 UI 构造。
`.rml` 是纯视图声明,`.rml.rs` 是纯业务逻辑。设计师与工程师可并行工作,互不干扰。这一原则带来的副产品是:UI 变更(`.rml`)与逻辑变更(`.rml.rs`)在代码审查时可以独立聚焦,设计资产可以独立沉淀。
counter.rml ← 设计师编辑:结构、样式、绑定
counter.rml.rs ← 工程师编辑:状态、命令、生命周期
③ HTML 语法优先
> 降低 Web 开发者进入 Rust 桌面的门槛。
- 标准 HTML 标签:`div`、`button`、`input`、`p`、`ul`、`li` - 标准 HTML 属性:`class`、`id`、`style`、`placeholder`、`type` - 标准事件模型:`on-click`、`oninput`、`onkeydown`
任何写过 HTML 的开发者,打开 `.rml` 文件的第一秒就能读懂结构。RML 不发明新语法,只通过极简指令(`if`、`each`、`show`)扩展能力,且**无任何框架前缀**。
1.1.4 设计哲学的取舍
任何框架设计都是取舍。RML 明确选择了以下立场:
| 取舍维度 | RML 的选择 | 放弃了什么 | | ------------- | ---------------- | ---------------------- | | **语法亲和力** | HTML 优先 | 放弃了 Rust 宏语法的类型安全表达力 | | **关注点分离** | 文件级强分离 | 放弃了在同一文件内快速切换的便利 | | **编译期生成** | 零运行时开销 | 放弃了运行时动态加载模板的灵活性 | | **MVVM 范式** | 严格三层 | 放弃了"想写哪就写哪"的自由度 | | **GPUI 原生** | 编译到 GPUI 代码 | 放弃了跨后端能力(暂留作未来方向) |
这些取舍共同构成了 RML 的"性格":**保守、严谨、工业化**。它不为追求语法糖的灵活性而牺牲可维护性,不为追求运行时动态而牺牲性能。
1.1.5 与现有方案的定位差异
| 维度 | 原生 GPUI | gpui-rsx | **RML(本方案)** | | -------- | ------------- | ------------- | ---------------- | | UI 定义位置 | Rust 代码内 | Rust 代码内(宏) | **独立 `.rml` 文件** | | 语法风格 | 链式调用 | JSX-like | **纯 HTML/XML** | | UI/逻辑分离 | 无 | 弱 | **强(文件级分离)** | | 设计师可参与 | 否 | 否 | **是** | | 热重载 | 否 | 否 | **是** | | 学习曲线 | 陡 | 中 | **平缓** | | 代码量 | 100% | ~50% | **~35%** | | IDE 工具支持 | Rust-analyzer | Rust-analyzer | **XML 工具链全支持** |
RML 不是 GPUI 的替代品,而是 GPUI 之上的一层**工业化开发范式**。它把 GPUI 的渲染能力封装在标准化的 MVVM 流程背后,让团队可以规模化地交付桌面应用。
1.1.6 小结
RML 的设计理念可以浓缩为一句话:
> **"HTML 的语法亲和力 + WPF 的设计理念 + GPUI 的原生性能。"**
记住三条原则,你就掌握了判断 RML 任何设计决策的尺子:
1. 声明式优于命令式 2. 逻辑与表现彻底分离 3. HTML 语法优先
下一节 → [1.2 架构总览](./architecture.md)