component 属性宏
2026/5/15大约 2 分钟euvuirustwasmmacroscomponent
使用方式
使用 #[component] 属性宏标记函数组件,html! 宏在编译时扫描项目源码查找所有 #[component] 标记的函数,将其识别为自定义组件:
use euv::*;
#[derive(Clone, Default)]
struct MyCardProps {
title: &'static str,
}
#[component]
pub fn my_card(node: VirtualNode<MyCardProps>) -> VirtualNode {
let MyCardProps { title, .. }: MyCardProps = node.try_get_props().unwrap_or_default();
let children: VirtualNode = node.try_get_child_node();
html! {
div {
h3 { title }
children
}
}
}使用:
html! {
my_card {
title: "Hello"
p { "Card content" }
}
}提示
#[component] 属性宏本身是透传的(不会修改函数体),但它是 html! 宏识别组件的必要标记。只有被 #[component] 标记的函数才会在 html! 宏中作为组件标签使用,未标记的标识符一律被视为原生 HTML 元素。
获取 Props 和 Children
组件函数接收 VirtualNode<T> 参数,通过以下方法获取数据:
| 方法 | 返回类型 | 说明 | |
|---|---|---|---|
node.try_get_props() | Option<T> | 获取 Props 结构体(需 T: Clone) | |
node.try_get_child_node() | VirtualNode | 获取子节点(无子节点返回 VirtualNode::Empty,多个子节点返回 VirtualNode::Fragment) |
注意
Props 结构体必须派生 Clone 和 Default。Default 用于未传递属性时的默认值填充。Children 不应作为 Props 字段,而是通过 node.try_get_child_node() 获取。
组件属性映射
当 html! 宏识别到标签为组件时,属性名直接映射到 Props 结构体的字段名:
#[derive(Clone, Default)]
struct MyInputProps {
on_change: Option<Rc<dyn Fn(Event)>>,
on_submit: Option<Rc<dyn Fn(Event)>>,
data_id: &'static str,
}
#[component]
pub fn my_input(node: VirtualNode<MyInputProps>) -> VirtualNode {
let MyInputProps { on_change, on_submit, data_id, .. } = node.try_get_props().unwrap_or_default();
html! {
input {
oninput: on_change
data_id: data_id
}
}
}使用:
html! {
my_input {
on_change: my_handler
on_submit: my_submit_handler
data_id: "123"
}
}提示
组件属性名直接对应 Props 结构体字段名。html! 宏自动将属性值映射到结构体字段,未传递的字段使用 Default::default() 填充。回调属性类型为 Option<Rc<dyn Fn(Event)>>,字段名使用 on 前缀格式(如 onclick、on_change)。