前言
上一篇主要在回答一个问题:为什么是 Dioxus。
这一篇收窄一点,就做一件事:从零跑起一个 Dioxus 项目。
很多 Rust UI 框架,第一步就容易把人劝退。不是依赖太多,就是工具链太碎,再不然就是能跑起来,但你根本不知道项目结构为什么长这样。
Dioxus 这点还行。它有自己的 dx CLI,创建项目、启动开发服务器、切换平台,至少入门这段路没那么拧巴。
先说清楚,这篇不是官方文档翻译,也不是把 CLI 参数抄一遍。我只讲新手最关心的那条线:
- 装好工具
- 创建项目
- 看懂目录
- 改出第一个页面
- 跑热更新
- 切到桌面端
这 6 步走顺了,后面再学 rsx!、Signals、路由,心里会踏实很多。
1. 先把项目创建出来
1.1 安装 dx CLI
先装 Dioxus 的 CLI:
bash
curl -fsSL https://dioxuslabs.com/install.sh | bash
装完以后确认一下:
bash
dx --version
这里我建议顺手确认两个环境:
rustc --versioncargo --version
因为 dx 归根到底还是围绕 Rust 工具链在工作,不是另外搞了一套东西。你可以把它当成 Dioxus 官方给的一层开发入口。
1.2 创建第一个项目
直接新建:
bash
dx new hello-dioxus
cd hello-dioxus
然后启动:
bash
dx serve
默认会跑 Web 版,本地一般是:
text
http://localhost:8080
如果你之前用过 React、Vite 或 Next.js,这一步几乎没有理解成本。区别只是现在写 UI 的语言换成了 Rust。
2. 先别急着写代码,先看懂目录
dx new 生成的项目一般不复杂,大致会长这样:
text
hello-dioxus/
├── Cargo.toml
├── Dioxus.toml
├── assets/
│ └── main.css
└── src/
└── main.rs
先看 3 个地方就够了。
2.1 src/main.rs:应用入口
这个文件就是你第一天最常打交道的地方。应用怎么启动、根组件是什么、页面怎么写,最开始都在这里。
2.2 assets/main.css:样式入口
Dioxus 走的是 WebView / Web 这条路,所以你完全可以把它当成普通前端项目里的 CSS 入口。
这点很实在。它意味着:
- 你不是在学一套全新样式系统
- 你熟悉的 class、布局、响应式思路都还能用
- 后面接 Tailwind CSS 这类工具也比较自然
2.3 Dioxus.toml:Dioxus 的项目配置
这个文件里放的是 Dioxus 自己关心的项目配置,通常会涉及应用名称、资源、打包参数这些东西。
比如后面你要打桌面包、配图标、加资源,很多信息都会写在这里,而不是全塞进 Cargo.toml。
3. 默认生成的代码,已经把 Dioxus 的基本味道带出来了
新项目默认给的是一个计数器。别嫌它简单,这段代码已经把最常见的几个概念摆出来了。
rust
use dioxus::prelude::*;
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut count = use_signal(|| 0);
rsx! {
div {
h1 { "Count: {count}" }
button {
onclick: move |_| count += 1,
"Increment"
}
}
}
}
如果你有 React 背景,这里基本可以直接对照着看:
#[component]:声明一个组件App() -> Element:组件返回 UIuse_signal(|| 0):创建一个响应式状态rsx!:写界面onclick:绑定事件
这里先记一句就行:rsx! 不是模板文件,它就是 Rust 代码的一部分。这个感觉早点建立起来,后面学起来会顺很多。
4. 改出第一个自己的页面
官方默认计数器当然能跑,但有点太素了。我们把它改成一个更像页面的例子:带输入框的欢迎卡片。
rust
use dioxus::prelude::*;
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut name = use_signal(|| String::from("Dioxus"));
let mut clicks = use_signal(|| 0);
rsx! {
div {
class: "page",
h1 { "10 分钟跑起你的第一个 Dioxus 应用" }
p { "这个页面同时演示了 rsx!、事件绑定和 signals。" }
input {
value: "{name}",
oninput: move |evt| name.set(evt.value()),
placeholder: "输入你的名字"
}
button {
onclick: move |_| clicks += 1,
"点了我 {clicks} 次"
}
p {
"你好,{name}。欢迎来到 Dioxus。"
}
}
}
}
这个例子里有 3 个点,刚好能把入门阶段最常碰到的东西串起来。
4.1 rsx! 长得像 JSX,但它不是 JSX
你会发现这个宏跟 React 很像:
- 有标签层级
- 有属性绑定
- 有事件处理
- 有花括号插值
但写两下就会感觉到差异。
举个例子,属性值本质上还是 Rust 表达式:
rust
value: "{name}"
事件回调也是 Rust 闭包:
rust
oninput: move |evt| name.set(evt.value())
也就是说,你写 UI 的时候并没有离开 Rust。对 Rust 开发者来说,这一点很舒服。
4.2 use_signal 是你最早会反复碰到的状态能力
举个例子,上面的 clicks:
rust
let mut clicks = use_signal(|| 0);
点击按钮时更新它:
rust
onclick: move |_| clicks += 1,
在页面里直接读它:
rust
"点了我 {clicks} 次"
这套写法很短,读起来也直观。
如果非要先套一个类比,你可以暂时把它理解成更轻一点的 useState。当然底层不是一回事,Dioxus 走的是细粒度响应式,这个我后面单开一篇讲。
4.3 输入事件的写法,要先适应一下
新手第一眼最容易卡住的,往往是这个:
rust
oninput: move |evt| name.set(evt.value())
为什么不是 event.target.value?因为你现在不在浏览器 JavaScript 世界里了,事件对象是 Dioxus 抽象出来的 Rust 类型。
这不算难,但确实要适应一下。
我的建议很简单:先别急着把所有事件类型都搞明白,先把输入框、按钮、列表这些高频场景写顺。后面再回来看事件模型,会轻松不少。
5. 顺手加一点样式,你会更容易进入状态
比如在 assets/main.css 里加一点样式:
css
body {
margin: 0;
font-family: Inter, system-ui, sans-serif;
background: #f5f7fb;
color: #1f2937;
}
.page {
width: min(720px, calc(100vw - 32px));
margin: 48px auto;
padding: 32px;
background: #ffffff;
border-radius: 20px;
box-shadow: 0 18px 60px rgba(15, 23, 42, 0.08);
}
input,
button {
font: inherit;
padding: 12px 16px;
margin-right: 12px;
border-radius: 12px;
}
再刷新页面,你很快就会意识到,写 Dioxus 的 Web 或桌面 UI,很多时候就是在做前端那套事。
这也是它跟 Makepad 这类 Rust 原生渲染路线差异很大的地方。你不用先学一套新的布局 DSL,再慢慢适应它的规矩。以前写 CSS 的经验,大部分还能接着用。
6. dx serve 的热更新,确实会影响第一印象
这一段我建议你自己手动试一下,因为它很影响你接下来还想不想继续写。
启动:
bash
dx serve
然后分别试三种修改。
6.1 改文字内容
比如把:
rust
h1 { "10 分钟跑起你的第一个 Dioxus 应用" }
改成:
rust
h1 { "我的第一个 Dioxus 页面" }
页面会更新,反馈挺直接。
6.2 改 CSS
比如把卡片圆角从 20px 改成 28px,通常也能很快看到结果。
6.3 改 Rust 结构
比如新增依赖、改 Cargo.toml、调整大的类型定义,这种就别指望跟改 CSS 一样了,本质上还是重新编译。
所以我对 Dioxus 热更新的评价很简单:
- 改
rsx!内容,体验不错 - 改样式,体验不错
- 改小块逻辑代码,通常也还行
- 改工程结构和依赖,老老实实等编译
这很正常。它毕竟不是脚本语言,底层还是 Rust 编译链路。
7. 同一个项目切到桌面版,这一步最容易让人记住 Dioxus
Web 跑通以后,直接切桌面版:
bash
dx serve --platform desktop
如果环境没问题,你会看到一个桌面窗口弹出来,里面就是刚才那套页面。
有意思的不是"它能弹个窗",而是你会很直观地感受到:
刚才那套组件、状态、样式,几乎没怎么改,就到了另一个平台。
所以我一直觉得,Dioxus 的重点不是"Rust 也能写页面",而是同一套 Rust UI 可以继续往 Web、桌面、移动这几个方向走。
当然,桌面端不是没有现实约束。它当前主流路线依然是 WebView,所以:
- 原生感不一定比 Makepad 强
- 能力覆盖不一定比 Tauri 广
- 最终体验仍然受平台 WebView 影响
但如果只看第一天上手的感受,这一步确实挺加分。
8. 新手最容易踩的几个点
8.1 不要把它当成"Rust 版 HTML"
rsx! 看起来像标签,但你应该把它理解成 Rust 里的声明式 UI 语法,而不是模板文件。
这个心智转不过来,后面看条件渲染、列表渲染、组件组合时会一直拧巴。
8.2 状态是 Rust 值,不是随手乱改的动态对象
在 React 里,很多人已经习惯了"对象一包,状态一塞"。到了 Rust 这里,类型约束会逼着你把东西想清楚一点。
这不是坏事。前面会慢一点,后面项目大了反而稳。
8.3 热更新很好,但不要把它神化
很多文章会把"Rust 也能热更新"讲得很神。实际体验当然比纯 cargo run 强,但边界还是有的。
说白了,它已经够你日常改页面了,但还没到前端脚本生态那种想改啥就秒回的程度。
预期摆正,体验反而更舒服。
总结
如果只看第一天上手,Dioxus 给我的感觉是:比我预想里顺,很多地方也确实像 React;但一碰到状态和类型,Rust 的味道马上就回来了。
这一篇我们做了 6 件事:
- 安装
dx - 创建项目
- 看懂目录
- 改出第一个带状态的页面
- 试了热更新
- 切到了桌面端
写到这里,你其实已经跨过了 Dioxus 入门最关键的一步:不是知道它有这么个框架,而是真的把它跑起来了。
下一篇我会单独拆 rsx!:条件渲染怎么写、列表渲染怎么写、属性绑定和 JSX 到底哪里一样,哪里不一样。这个东西弄明白了,后面看组件和路由会轻松很多。
如果你已经跑过 Dioxus,第一个让你觉得"哦,这个框架有点意思"的瞬间是什么?评论区聊聊。