使用RSX构建用户界面
Dioxus会将内容渲染为HTML格式。若您不熟悉HTML,本指南将帮助您掌握基础知识。更多详细信息可参考MDN文档。
文本节点
任何用引号包围的内容在rsx中都会渲染为文本节点:
rust
rsx! {
"Hello world"
}
您可以在文本中包含格式化片段,就像使用 format!
宏一样:
rust
let user = use_signal(|| User {
name: "Dioxus".to_string(),
});
rsx! {
// Unlike the format macro, you can include many expressions inline in the formatted text
"Hello {user.read().name}"
}
元素
HTML最基本的构建单元是元素。在rsx中,你可以通过名称后跟大括号来创建元素。最常见的元素之一是input元素。input元素创建一个交互式输入框:
rust
rsx! {
input {}
}
额外说明:Web组件名称中包含连字符的元素即为Web组件。Web组件在dioxus中直接渲染且不进行类型检查。我们建议将Web组件封装在类型安全的组件中,以提升使用便捷性。
rust
rsx! {
my-web-component {}
}
属性
属性为元素提供额外信息。在元素大括号内,通过 input
属性名称、冒号及值(通常为格式化字符串)即可在dioxus中指定属性。我们可利用属性设置输入元素的类型 type
。默认类型为文本(显示文本输入框),但可将其设为number
类型以仅接受数字输入:
rust
rsx! {
input { type: "number" }
}
与文本节点类似,属性也可以包含格式化片段。我们可以将input元素的值设置为信号来控制它:
rust
let mut value = use_signal(|| "Hello world".to_string());
rsx! {
input { value: "{value}" }
}
条件属性
您可以通过将属性值设置为未终止的if语句来条件性地设置属性。如果if语句评估为真,则该属性将被设置:
rust
let number_type = use_signal(|| false);
rsx! {
input { type: if number_type() { "number" } }
}
事件监听器
事件监听器可用于响应用户输入。在rsx
中,事件处理程序始终以on
开头。其语法与常规属性相同,但事件处理程序仅接受响应事件的闭包 。我们可以为input
元素的oninput
事件附加事件监听器,以监听输入内容的变化:
rust
let mut value = use_signal(|| "Hello world".to_string());
rsx! {
input {
oninput: move |event| value.set(event.value()),
value: "{value}"
}
}
子元素
在添加所有属性和事件监听器之后,您可以在元素中添加子元素。元素可以接受文本、组件或其他元素作为子元素。我们可以在输入框周围添加一个div元素来居中显示:
rust
rsx! {
div {
// display sets the layout mode of the element
display: "flex",
// justify-content centers the element horizontally
justify_content: "center",
input {
type: "number"
}
}
}
循环
您可以在 rsx
中直接插入 for
循环。循环体可接受任意数量的子元素,这些子元素将在每次循环迭代时渲染。HTML
中的 ul
元素会渲染一个无序列表,其中包含任意数量的 li
(列表项)元素。我们可以利用这两个元素在循环中渲染项目列表:
rust
let mut items = use_signal(|| vec!["Hello", "Dioxus"]);
rsx! {
ul {
for item in items.iter() {
li { "{item}" }
}
}
}
列表中的每个项都应具有在多次重渲染过程中保持稳定的唯一值,称为键 。键用于在比较差异时识别项的移动方式。若无键,在列表中重新排序项时,很容易意外丢失或移动状态。我们可通过使用 key
属性为列表项添加键:
rust
let mut items = use_signal(|| vec!["Hello", "Dioxus"]);
rsx! {
ul {
for item in items.iter() {
li { key: "{item}", "{item}" }
}
}
}
if 语句
在 rsx
中也可使用 if/else
语句。if
语句的每个分支都接受子节点,当条件为真时这些子节点将被渲染。我们可以使用 if
语句来条件性地渲染登录界面:
rust
let logged_in = use_signal(|| false);
rsx! {
div {
if logged_in() {
"You are logged in"
} else {
"You are not logged in"
}
}
}
为何选择RSX而非HTML?
若您见过React
的JSX
或Rust语言的html!{}
宏,或许会好奇Dioxus
为何选择自定义语法而非更接近HTML
的语法。
原因如下:
- RSX无需额外工具即可实现代码高亮和代码折叠
- RSX输入更快捷------大括号自动闭合
- RSX并非全是HTML------Dioxus可在非HTML场景中使用
- HTML不符合Rust语法规范------并非所有HTML元素都能在
html!{}
中使用