#user-interface #cross-platform-ui #ui-framework #ui #dom #react

dioxus

适用于在 Rust 中构建跨平台用户界面的便携、高效和人性化的框架

26 个版本

0.6.0-alpha.22024 年 8 月 7 日
0.5.6 2024 年 7 月 18 日
0.5.0 2024 年 3 月 28 日
0.4.3 2023 年 12 月 7 日
0.1.0 2021 年 1 月 20 日

#9 in GUI

Download history 4680/week @ 2024-05-04 4964/week @ 2024-05-11 4763/week @ 2024-05-18 4490/week @ 2024-05-25 5110/week @ 2024-06-01 3855/week @ 2024-06-08 4639/week @ 2024-06-15 4762/week @ 2024-06-22 3104/week @ 2024-06-29 2403/week @ 2024-07-06 3523/week @ 2024-07-13 3441/week @ 2024-07-20 3771/week @ 2024-07-27 3600/week @ 2024-08-03 4051/week @ 2024-08-10 3105/week @ 2024-08-17

15,065 每月下载量
用于 101 个 Crates (97 直接)

MIT/Apache

770KB
13K SLoC

🌗🚀 Dioxus

适用于 Rust 的并发、函数式、虚拟 DOM

资源

本概述简要介绍了 Dioxus。如需深入了解,请务必查看

概述和目标

Dioxus 使您能够轻松快速地使用 Rust 构建复杂的用户界面。任何 Dioxus 应用都可以在网页浏览器、桌面应用程序、移动应用程序或其他任何地方运行,只要您构建了正确的渲染器。

Dioxus 严重受到 React 的启发,支持许多相同的概念

  • 状态钩子
  • 虚拟 DOM 和 diffing
  • 并发、纤程和异步渲染
  • 类似 JSX 的模板语法

如果您了解 React,那么您就了解 Dioxus。

Dioxus 的性能比许多其他 Rust UI 库(Yew/Percy)要高得多,并且比 React 的性能要高得多——与 InfernoJS 竞争力相当。

请记住:Dioxus 是一个用于声明交互式用户界面的库——它不是一个专门的渲染器。大多数 Dioxus 的官方渲染器目前仅支持 Web 技术。

简要概述

所有 Dioxus 应用都是通过组合以大写字母开头的函数并返回一个 Element 来构建的。

要启动应用程序,我们使用 launch 方法,并在 Cargo.toml 中使用功能来指定我们想要使用的渲染器。在启动函数中,我们传递应用程序的根 Component

use dioxus::prelude::*;

fn main() {
    launch(App);
}

// The #[component] attribute streamlines component creation.
// It's not required, but highly recommended. It will lint incorrect component definitions and help you create props structs.
#[component]
fn App() -> Element {
    rsx! { "hello world!" }
}

元素和您的第一个组件

您可以使用 rsx! 宏使用类似 JSX 的语法创建元素。在 rsx! 中的任何元素都可以有属性、监听器和子元素。为了保持一致性,我们强制将所有属性和监听器列在子元素之前。

# use dioxus::prelude::*;
let value = "123";

rsx! {
    div {
        class: "my-class {value}",                  // <--- attribute
        onclick: move |_| println!("clicked!"),   // <--- listener
        h1 { "hello world" }                       // <--- child
    }
};

rsx! 接受“结构体形式”的属性。任何实现 IntoDynNode 的 Rust 表达式,只要它包含在大括号内,都将被解析为子元素。我们有两个例外:对于循环和条件语句,它们的主体将被解析为 rsx 节点。

# use dioxus::prelude::*;
rsx! {
    div {
        for _ in 0..10 {
            span { "hello world" }
        }
    }
};

将所有这些放在一起,我们可以编写一个简单的组件来渲染元素列表

# use dioxus::prelude::*;
#[component]
fn App() -> Element {
    let name = "dave";
    rsx! {
        h1 { "Hello, {name}!" }
        div { class: "my-class", id: "my-id",
            for i in 0..5 {
                div { "FizzBuzz: {i}" }
            }
        }
    }
}

组件

我们可以组合这些函数组件来构建复杂的应用程序。我们设计的每个新组件都必须接受一些属性。对于没有显式属性的组件,我们可以完全省略类型。

在 Dioxus 中,所有属性默认使用 Clone 和 PartialEq 进行记忆化。对于无法克隆的属性,只需将字段包装在 ReadOnlySignal 中,Dioxus 将为您处理类型转换。

# use dioxus::prelude::*;
# #[component] fn Header(title: String, color: String) -> Element { todo!() }
#[component]
fn App() -> Element {
    rsx! {
        Header {
            title: "My App",
            color: "red",
        }
    }
}

#[component] 将帮助我们自动为组件创建属性结构体。

# use dioxus::prelude::*;
// The component macro turns the arguments for our function into named fields we can pass in to the component in rsx
#[component]
fn Header(title: String, color: String) -> Element {
    rsx! {
        div {
            background_color: "{color}",
            h1 { "{title}" }
        }
    }
}

您可以在 参考文档 中了解更多关于属性的信息。

钩子

虽然组件是 UI 元素的重复使用形式,但钩子是逻辑的重复使用形式。钩子提供了一种从 Dioxus 内部 Scope 获取状态并将其用于渲染 UI 元素的方法。

按照惯例,所有钩子都是以 use_ 开头的函数。我们可以使用钩子来定义状态并在监听器内部修改它。

# use dioxus::prelude::*;
#[component]
fn App() -> Element {
    // The use signal hook runs once when the component is created and then returns the current value every run after the first
    let name = use_signal(|| "world");

    rsx! { "hello {name}!" }
}

钩子对它们的用法很敏感。要使用钩子,您必须遵守 “钩子规则”

  • 钩子只能在组件或另一个钩子的主体中调用。不能在循环、条件或函数调用等表达式内部调用。
  • 钩子应以 "use_" 开头

从某种意义上说,钩子让我们能够在不显式声明状态结构体的情况下为组件添加一个状态字段。然而,这意味着我们需要以正确的顺序“加载”该结构体。如果顺序错误,钩子将选择错误的状态并引发恐慌。

Dioxus 包含许多内置钩子,您可以在组件中使用。如果这些钩子不符合您的用例,您还可以通过 自定义钩子 扩展 Dioxus。

综合起来

使用组件、rsx 和钩子,我们可以构建一个简单的应用程序。

use dioxus::prelude::*;

fn main() {
    launch(App);
}

#[component]
fn App() -> Element {
    let mut count = use_signal(|| 0);

    rsx! {
        div { "Count: {count}" }
        button { onclick: move |_| count += 1, "Increment" }
        button { onclick: move |_| count -= 1, "Decrement" }
    }
}

结论

这个概述没有涵盖所有内容。请务必查看官方网站上的 教程参考,以获取更多详细信息。

除了这个概述之外,Dioxus 还支持

  • 服务器端渲染
  • 并发渲染(具有异步支持)
  • Web/Desktop/移动设备支持
  • 预渲染和恢复
  • 片段和 Suspense
  • 内联样式
  • 自定义事件处理程序
  • 自定义元素
  • 基本细粒度反应性(类似于 IE SolidJS/Svelte)
  • 等等!

构建酷炫的东西 ✌️

依赖关系

~2–47MB
~734K SLoC