在下面使用日志 r
log = "0.4" env_logger = "0.9"
Event Handlers
Event handler用于响应用户操作。例如,当用户点击、滚动、移动鼠标或输入字符时,可能会event handler。
Event handler附加到元素上。例如,我们通常不关心应用程序内发生的所有点击,只关心特定按钮上的点击。
Event handler类似于常规属性,但它们的名称通常以on开头,并接受闭包作为值。当它监听的事件被触发时,闭包将被调用,并传递该事件。
例如,要处理元素上的点击,我们可以指定一个onclick处理器:
rsx! {
button { onclick: move |event| log::info!("Clicked! Event: {event:?}"), "click me!" }
}
Event对象
Event handler接收一个包含有关event信息的Event对象。不同类型的事件包含不同类型的数据。例如,与鼠标相关的事件包含MouseData,它告诉你鼠标点击的位置以及使用了哪些鼠标按钮。
在上面的例子中,这个事件数据被记录到了终端:
Clicked! Event: UiEvent { bubble_state: Cell { value: true }, data: MouseData { coordinates: Coordinates { screen: (242.0, 256.0), client: (26.0, 17.0), element: (16.0, 7.0), page: (26.0, 17.0) }, modifiers: (empty), held_buttons: EnumSet(), trigger_button: Some(Primary) } }
Clicked! Event: UiEvent { bubble_state: Cell { value: true }, data: MouseData { coordinates: Coordinates { screen: (242.0, 256.0), client: (26.0, 17.0), element: (16.0, 7.0), page: (26.0, 17.0) }, modifiers: (empty), held_buttons: EnumSet(), trigger_button: Some(Primary) } }
要了解HTML提供的不同类型的事件类型,请参阅事件模块文档。
Event传播
有些事件会首先在事件起源的元素上触发,然后向上传播。例如,在div内的button上的点击事件会首先触发按钮的事件监听器,然后是div的事件监听器。
关于事件传播的更多信息,请参阅mdn文档中的事件冒泡
如果你想阻止这种行为,可以在事件上调用stop_propagation():
rsx! {
div { onclick: move |_event| {},
"outer"
button {
onclick: move |event| {
event.stop_propagation();
},
"inner"
}
}
}
防止默认行为
有些事件有默认行为。对于键盘事件,这可能是输入字符。对于鼠标事件,这可能是选择文本。
在某些情况下,你可能想要避免这种默认行为。为此,你可以添加prevent_default属性,用你想要阻止的handler的名称命名。这个属性可以用于多个handler,使用它们的名字通过空格分隔:
rsx! {
a {
href: "https://example.com",
prevent_default: "onclick",
onclick: |_| log::info!("link clicked"),
"example.com"
}
}
任何事件handler仍将被调用。
通常,在React或JavaScript中,你会在回调中的事件上调用"preventDefault"。Dioxus目前不支持这种行为。注意:这意味着你不能根据事件中的数据有条件地防止默认行为。
处理器属性
有时,你可能想要创建一个接受event handler的组件。一个简单的例子是一个FancyButton组件,它接受一个onclick处理器:
#[derive(PartialEq, Clone, Props)]
pub struct FancyButtonProps {
onclick: EventHandler<MouseEvent>,
}
pub fn FancyButton(props: FancyButtonProps) -> Element {
rsx! {
button {
class: "fancy-button",
onclick: move |evt| props.onclick.call(evt),
"click me pls."
}
}
}
然后,你可以像使用任何其他handler一样使用它:
rsx! {
FancyButton {
onclick: move |event| println!("Clicked! {event:?}"),
}
}
注意:就像任何其他属性一样,你可以给处理器命名任何你想要的名字!你传递的任何闭包都将自动转换为
EventHandler。
异步事件处理器
作为属性传递的EventHandler不支持传递返回异步块的闭包。相反,你必须手动调用spawn来进行异步操作:
rsx! {
FancyButton {
// 这不行!
// onclick: move |event| async move {
// println!("Clicked! {event:?}");
// },
// 这样可以!
onclick: move |event| {
spawn(async move {
println!("Clicked! {event:?}");
});
},
}
}
这只适用于作为属性的自定义event handler。
自定义数据
Event handler对任何类型都是通用的,所以你可以向它们传递任何你想要的数据,例如:
struct ComplexData(i32);
#[derive(PartialEq, Clone, Props)]
pub struct CustomFancyButtonProps {
onclick: EventHandler<ComplexData>,
}
pub fn CustomFancyButton(props: CustomFancyButtonProps) -> Element {
rsx! {
button {
class: "fancy-button",
onclick: move |_| props.onclick.call(ComplexData(0)),
"click me pls."
}
}
}