Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Dioxus 是一个 Rust 的全栈跨平台应用框架,支持服务端渲染、实时更新和类似 React 的组件模型。当用户需要使用 Dioxus 构建 Web 应用、创建组件、处理状态、路由、或处理数据获取时使用。
Dioxus 是一个 Rust 的全栈跨平台应用框架,支持服务端渲染、实时更新和类似 React 的组件模型。当用户需要使用 Dioxus 构建 Web 应用、创建组件、处理状态、路由、或处理数据获取时使用。
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Dioxus 是一个现代 Rust Web 框架,结合了 React 的编程模型与 Rust 的性能优势。它允许你构建高性能的 Web 应用,支持服务端渲染(SSR)、实时更新和跨平台部署。
# 在 Rust 项目中添加 Dioxus cargo add dioxus --features ssr # 使用 CLI 工具 cargo install dioxus-cli
src/ ├── main.rs # 应用入口 ├── App.rsx # 根组件 ├── components/ # 子组件目录 ├── routes/ # 路由模块 ├── server_fn/ # 服务端函数 └── utils/ # 工具函数
组件是使用 #[component] 宏定义的函数,它接受 Properties(props)并返回一个 Element。 use dioxus::prelude::*; #[component] fn DogApp(breed: String) -> Element { rsx! { div { class: "card" } { h2 { "Dogs of breed: {breed}" } ul { (0..3).map(|i| rsx! { li { "Dog {i}" } }) } } } }
所有组件都接受一个描述其参数的 struct。Props 需要 derive 以下 traits: #[derive(Props, PartialEq, Clone)] struct DogAppProps { breed: String, } 重要特性: 特性说明Props组件接受的参数对象PartialEqual允许部分更新 propsClone允许克隆 propsMemoized默认 memoized,只有 props 改变时重新渲染
Dioxus 组件会在以下情况下重新渲染: Props 改变:当组件的 props 发生变化时 信号变化:当组件监听的信号更新时 Scope.needs_update():当父组件要求更新时 重要: Dioxus 默认 memoized 所有组件,性能比 React 更好。
Dioxus 提供类似 React 的 hooks 用于管理状态。 use_signal() 创建响应式状态: #[component] fn Counter() -> Element { let mut count = use_signal(cx, || 0); rsx! { div { button { onclick: move |_| { count += 1; } } { "Increment" } p { "Count: {count}" } button { onclick: move |_| { count -= 1; } } { "Decrement" } } } } use_coroutine() 运行异步操作: #[component] fn DataFetcher() -> Element { let mut data = use_signal(cx, || None::<String>); let loading = use_signal(cx, || false); use_coroutine(cx, |cx| async move { loading.set(true); // 模拟异步数据获取 tokio::time::sleep(Duration::from_secs(2)).await; data.set(Some("Fetched data".to_string())); loading.set(false); }); rsx! { div { if *loading.get() { p { "Loading..." } } else if let Some(d) = data.get() { p { "Data: {d}" } } else { p { "No data yet" } } } } } use_context() 访问上下文值: #[derive(Clone, Props)] struct ChildProps { value: String, } #[component] fn Child(props: ChildProps) -> Element { rsx! { p { "Value from context: {props.value}" } } } #[component] fn Parent() -> Element { let value = use_context(cx, || "default".to_string()); rsx! { Child { value: value.clone() } } }
使用信号进行全局状态管理: // main.rs use dioxus::prelude::*; fn main() { let theme_signal = RwSignal::new("light".to_string()); dioxus::launch(App, ( AppContext::new(theme_signal) )); } // App.rsx #[component] fn App() -> Element { let theme = use_context(cx); rsx! { div { button { onclick: move |_| theme.set("dark".to_string()) } { "Dark Mode" } button { onclick: move |_| theme.set("light".to_string()) } { "Light Mode" } p { "Current theme: {theme.read()}" } } } }
// routes/mod.rs use dioxus::prelude::*; use dioxus::router::{Route, Router}; #[component] fn Home() -> Element { rsx! { h1 { "Home Page" } } } #[component] fn About() -> Element { rsx! { h1 { "About Page" } } } // App.rsx #[component] fn App() -> Element { rsx! { Router { Route { to: "/", Home {} } Route { to: "/about", About {} } } } }
use dioxus::router::NavLink; rsx! { nav { ul { li { NavLink { to: "/" } { "Home" } } li { NavLink { to: "/about" } { "About" } } } } }
#[derive(Props, Clone)] struct FormProps { on_submit: Callback<String>, } #[component] fn Form(props: FormProps) -> Element { let mut name = use_signal(cx, || String::new()); let mut email = use_signal(cx, || String::new()); rsx! { form { onsubmit: move |event| { event.prevent_default(); props.on_submit.call(( name.get().clone(), email.get().clone(), )); } } { input { r#type: "text", value: "{name}", oninput: move |e| name.set(e.value()) } input { r#type: "email", value: "{email}", oninput: move |e| email.set(e.value()) } button { r#type: "submit" } { "Submit" } } } }
// main.rs use dioxus::prelude::*; fn main() { // 启用 SSR 功能 dioxus::launch(App); } // server_fn/api.rs use dioxus::prelude::*; #[server_fn("/")] async fn serve_home() -> String { // 渲染组件为字符串 render_to_string(|cx| rsx! { App {} }) }
use dioxus::prelude::*; #[server_fn("/api/hello")] async fn hello(name: String) -> String { format!("Hello, {}!", name) }
#[server_fn("/api/data")] async fn fetch_data() -> Json<Vec<String>> { use crate::data::fetch_from_db().await }
rsx! { div { if *count.get() > 0 { p { "Count is positive" } } else { p { "Count is zero" } } } }
let items = vec!["Item 1", "Item 2", "Item 3"]; rsx! { ul { items.iter().map(|item| rsx! { li { key: "{item}" } { item } }) } }
#[component] fn Header() -> Element { rsx! { header { h1 { "My App" } nav { a { href: "/" } { "Home" } a { href: "/about" } { "About" } } } } } #[component] fn PageLayout(content: Element) -> Element { rsx! { div { class: "layout" } { Header {} main { content } Footer {} } } }
// 在 main.rs 或组件中导入样式 use dioxus::prelude::*; // styles.css .card { background-color: white; padding: 1rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); }
rsx! { div { style: "background-color: #f0f0f0; padding: 1rem;" { "Content" } } }
// Cargo.toml [dependencies] dioxus = { version = "0.7", features = ["fullstack"] } // 在组件中使用 rsx! { div { class: "bg-blue-500 text-white p-4 rounded" } { "Styled" } }
#[component] fn ErrorBoundary() -> Element { rsx! { div { p { "Something went wrong!" } button { onclick: move |_| { // 重试逻辑 } } { "Retry" } } } }
#[component] fn ValidatedInput(props: ValidatedInputProps) -> Element { rsx! { input { value: "{props.value}", r#type: props.input_type, disabled: props.disabled, } } }
Dioxus 默认 memoized 所有组件。对于昂贵的计算,可以使用 use_memo: use dioxus::hooks::*; #[component] fn ExpensiveCalculation() -> Element { let count = use_signal(cx, || 0); let result = use_memo(cx, move || { // 昂贵的计算 expensive_calculation(*count) }, (*count)); rsx! { div { p { "Result: {result}" } } } }
使用 PartialEqual 和 use_memo 来最小化重新渲染。
#[cfg(test)] mod tests { use super::*; use dioxus::prelude::*; #[test] fn test_dog_app_renders() { let breed = "Golden Retriever".to_string(); let vnode = dioxus::ssr::render_to_string(|cx| rsx! { DogApp { breed: breed.clone() } }); assert!(vnode.contains(&breed)); } }
cargo build --release
cargo install tauri-cli tauri build
FROM rust:1.70-slim WORKDIR /app COPY . . RUN cargo build --release CMD ["./target/release/my-app"]
详细文档和更多示例,请参考: Dioxus 文档 组件参考 GitHub Discord 社区 Twitter
A: 使用 use_coroutine hook 来运行异步代码并更新状态。
A: 使用 props 传递数据,使用全局上下文管理全局状态。
A: 使用 dioxus::router 提供的路由组件和 NavLink 进行导航。
A: Dioxus 默认 memoized 组件,使用 use_memo 进行昂贵的计算。
A: 是的,Dioxus 支持服务端渲染(SSR)和静态站点生成(SSG)。
A: 使用服务端函数(Server Functions)或异步 hooks 来获取数据。
A: Dioxus 是纯 Rust 框架,但可以使用 wasm-bindgen 与 TypeScript 交互。
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.