域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

dioxus 组件与 rsx

本章将开始第一个案例:计数器的编写。首先,我们需要学习 dioxus 组件的编写和 rsx 语法。

Dioxus 和 React

如果你用过 React,你会发现 Dioxus 和它非常相似,你甚至可以将其视为 rust 版的 React。

  • 和 React 一样,Dioxus 也是通过组件来组织项目的。
  • React 使用 jsx 来编写组件,dioxus 使用 rsx 来编写组件。

如果你愿意,建议花点时间学习一下 React

创建项目

开始之前,我们需要创建一个名为 calc 的 dioxus 项目:

dx new calc

我们来看一下文件结构:

├── assets
│   ├── favicon.ico
│   ├── header.svg
│   └── main.css
├── Cargo.toml
├── Dioxus.toml
├── README.md
└── src
    └── main.rs
  • assets:放置图片、CSS等静态资源
  • Cargo.toml:如果连这都不知道,就不要搞了
  • Dioxus.toml:Dioxus 配置文件
  • src:源代码

打开 src/main.rs ,我们先来看看 dx 生成的 dioxus Web 项目的代码:

use dioxus::prelude::*;

const FAVICON: Asset = asset!("/assets/favicon.ico");
const MAIN_CSS: Asset = asset!("/assets/main.css");
const HEADER_SVG: Asset = asset!("/assets/header.svg");
  • 首先,引入来 dioxus::prelude 下的所有成员
  • 然后,使用 asset! 宏定义了3个类型为 Asset 的常量
    • 这3个常量都是静态资源,由此可知,在 dioxus 中,如果要导入静态资源,需要使用 asset!
    • 静态资源的路径,需要由 / 开头

接下来,我们看到 main 函数的定义:

  • 通过 dioxus::launch() 函数来启动 dioxus 应用
  • 其中的参数 App 是一个组件定义

我们看看 App 组件:

#[component]
fn App() -> Element {
    rsx! {
        document::Link { rel: "icon", href: FAVICON }
        document::Link { rel: "stylesheet", href: MAIN_CSS }
        Hero {}

    }
}

如果没有函数体中的 rsx! 宏,那么,这个函数非常简单,不是吗?

#[component]
pub fn Hero() -> Element {
    rsx! {
        div {
            id: "hero",
            img { src: HEADER_SVG, id: "header" }
            div { id: "links",
                a { href: "https://dioxuslabs.com/learn/0.6/", "📚 Learn Dioxus" }
                a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" }
                a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" }
                a { href: "https://github.com/DioxusLabs/sdk", "  Dioxus Development Kit" }
                a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" }
                a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" }
            }
        }
    }
}

其中的 rsx 看似很复杂对吗?其实,它对应的 HTML 如下:

<div id="hero">
    <img src="{HEADER_SVG}" id="header" />
    <div id="links">
        <a href="https://dioxuslabs.com/learn/0.6/">📚 Learn Dioxus</a>
        <a href="https://dioxuslabs.com/awesome">🚀 Awesome Dioxus</a>
        ...
		<a href="https://discord.gg/XgGxMSkvUM">👋 Community Discord</a>
    </div>
</div>

清理初始代码

我们先来清理一下初始文件和代码。

  • 首先,删除 assets/headers.svg 文件
  • 然后,打开 src/main.rs
    • 删除 HEADER_SVG常量,即删除 const HEADER_SVG: Asset = asset!("/assets/header.svg");
    • 删除 Hero 组件的定义,以及 App 组件中对该组件的调用
use dioxus::prelude::*;

const FAVICON: Asset = asset!("/assets/favicon.ico");
const MAIN_CSS: Asset = asset!("/assets/main.css");

fn main() {
    dioxus::launch(App);
}

#[component]
fn App() -> Element {
    rsx! {
        document::Link { rel: "icon", href: FAVICON }
        document::Link { rel: "stylesheet", href: MAIN_CSS }

        div { "Hello, 世界" }
    }
}

定义组件

我们大概看了 dioxus 如何定义组件。现在,我们手动定义一个简单的组件。

fn Hello() -> Element {
    rsx! {
        div { "Hello, 世界" }
    }
}

App 组件中调用:

#[component]
fn App() -> Element {
    rsx! {
        document::Link { rel: "icon", href: FAVICON }
        document::Link { rel: "stylesheet", href: MAIN_CSS }

        Hello {}
    }
}

我们来看下如何在 rsx 中插入一个值:

fn Hello() -> Element {
    let name = "AXUM中文网";
    rsx! {
        div { "Hello, {name}" }
    }
}

rsx 允许使用 {}进行插值操作,如上例的 div { "Hello, {name}" }

现在,我们为Hello 组件添加 Props

#[derive(Props, Clone, PartialEq)]
struct HelloProps {
    name: String,
}
fn Hello(props: HelloProps) -> Element {
    rsx! {
        div { "Hello, {props.name}" }
    }
}
  • HelloProps 结构体就是 Hello 组件的 Props,它包含一个 name 成员
    • 它需要 #[derive(Props, Clone, PartialEq)]
  • fn Hello(props: HelloProps)Hello 组件接收 HelloProps 类型的参数

对于组件而言,Props是一个非常重要且常用的。如果每个组件的Props都要这样单独定义一个结构体,那会非常麻烦。好在 dioxus 提供了 #[component],以下代码和上述代码效果一样:

#[component]
fn Hello(name: String) -> Element {
    rsx! {
        div { "Hello, {name}" }
    }
}

#[component] 宏:

  • 自动将组件的 Props (参数)定义对应的结构体
  • 会消除函数命名不规范的警告

rsx

dioxus 使用的是一种称为 rsx 的语法来生成虚拟DOM。我们来看一下最简单的 rsx:

rsx! {
    div { "Hello, 世界" }
}

它将生成对应的虚拟DOM:

<div>
    Hello, 世界
</div>

由此可知:在 rsx 中,某个元素中的字符串,就是它渲染到页面的文本内容。

和 HTML 一样,rsx 也可以添加属性:

我们给 div 添加了 idclass 属性,对应的 HTML:

<div id="msg" class="text-red-500">
    Hello, 世界
</div>

由此可知:rsx 的属性是键值对,多个属性需要用逗号分割。

要查看完整内容,请先登录