mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
* tree-wide: update links to https://rustwasm.github.io/wasm-bindgen https://rustwasm.github.io/wasm-bindgen -> https://wasm-bindgen.github.io/wasm-bindgen https://rustwasm.github.io/docs/wasm-pack -> https://drager.github.io/wasm-pack/book/ https://rustwasm.github.io/wasm-pack -> https://github.com/drager/wasm-pack
547 lines
29 KiB
Plaintext
547 lines
29 KiB
Plaintext
---
|
||
title: '事件'
|
||
---
|
||
|
||
## 介紹
|
||
|
||
Yew 與 [`web-sys`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/) crate 集成,並使用該 crate 中的事件。下面的[表格](#event-types)列出了在 `html!` 巨集中接受的所有 `web-sys` 事件。
|
||
|
||
您仍然可以為下表中未列出的事件新增 [`Callback`](../function-components/callbacks.mdx),請參閱[手動事件監聽器](#manual-event-listener)。
|
||
|
||
## 事件類型
|
||
|
||
:::tip
|
||
所有的事件類型都在 `yew::events` 下重新匯出。
|
||
使用 `yew::events` 中的類型比手動將 `web-sys` 作為依賴項包含在您的 crate 中更容易確保版本相容性,
|
||
因為您不會使用與 Yew 指定的版本衝突的版本。
|
||
:::
|
||
|
||
事件監聽器的名稱是在 `html` 巨集中新增事件 `Callback` 時預期的名稱:
|
||
|
||
```rust
|
||
use yew::prelude::*;
|
||
|
||
html! {
|
||
<button onclick={Callback::from(|_| ())}>
|
||
// ^^^^^^^ event listener name
|
||
{ "Click me!" }
|
||
</button>
|
||
};
|
||
```
|
||
|
||
事件名稱是監聽器名稱去掉 "on" 前綴,因此 `onclick` 事件監聽器監聽 `click` 事件。查看本頁末的[完整事件清單](#available-events)及其類型。
|
||
|
||
## 事件捕獲 {#event-bubbling}
|
||
|
||
Yew 調度的事件遵循虛擬 DOM 層次結構,向上冒泡到監聽器。目前,僅支援監聽器的冒泡階段。請注意,虛擬 DOM 層次結構通常(但並非總是)與實際 DOM 層次結構相同。在處理[傳送門](../../advanced-topics/portals)和其他更高級技術時,這一區別很重要。對於良好實現的元件,直覺應該是事件從子元件冒泡到父元件。這樣,您在 `html!` 中所寫的層次結構就是事件處理程序觀察到的層次結構。
|
||
|
||
如果您不想要事件冒泡,可以透過呼叫
|
||
|
||
```rust
|
||
yew::set_event_bubbling(false);
|
||
```
|
||
|
||
在啟動應用程式*之前*。這會加快事件處理速度,但某些元件可能會因未收到預期的事件而中斷。請謹慎使用!
|
||
|
||
## 事件委託
|
||
|
||
可能會讓人驚訝的是,事件監聽器並不是直接註冊在它們被渲染的元素上。相反,事件是從 Yew 應用的子樹根節點委託的。不過,事件仍然以其原生形式傳遞,並且不會創建任何合成形式。這可能會導致 HTML 監聽器中預期的事件與 Yew 中出現的事件之間的不符。
|
||
|
||
- [`Event::current_target`] 指向 Yew 子樹根節點,而不是新增監聽器的元素。如果您想存取底層的 `HtmlElement`,請使用 [`NodeRef`](../function-components/node-refs.mdx)。
|
||
- [`Event::event_phase`] 總是 [`Event::CAPTURING_PHASE`]。在內部,事件將表現得像是在冒泡階段,事件傳播將被重播,並且事件會[向上冒泡](#event-bubbling),即虛擬DOM 中較高的事件監聽器將在較低的事件監聽器之後觸發。目前,Yew 不支援捕獲監聽器。
|
||
|
||
這也意味著由 Yew 註冊的事件通常會在其他事件監聽器之前觸發。
|
||
|
||
[`event::current_target`]: https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.current_target
|
||
[`event::event_phase`]: https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.event_phase
|
||
[`event::capturing_phase`]: https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html#associatedconstant.CAPTURING_PHASE
|
||
|
||
## 具備類型的事件目標
|
||
|
||
:::caution
|
||
在本節中,**target ([`Event.target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target))** 總是指的是事件從其派發的元素。
|
||
|
||
這**不一定**總是指 `Callback` 所放置的元素。
|
||
:::
|
||
|
||
在事件 `Callback` 中,您可能想要取得該事件的目標。例如,`change` 事件沒有提供任何訊息,但用於通知某些內容已更改。
|
||
|
||
在 Yew 中,以正確的類型獲取目標元素可以透過幾種方式完成,我們將在這裡逐一介紹。呼叫事件上的[`web_sys::Event::target`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.target) 傳回一個可選的[ `web_sys::EventTarget`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.EventTarget.html) 類型,當您想知道輸入元素的值時,這可能看起來不太有用。
|
||
|
||
在下面的所有方法中,我們將解決相同的問題,以便清楚地了解方法的不同之處,而不是手邊的問題。
|
||
|
||
**問題:**
|
||
|
||
我們在 `<input>` 元素上有一個 `onchange` `Callback`,每次呼叫時,我們希望向元件發送一個[更新](components#update) `Msg`。
|
||
|
||
我們的 `Msg` 列舉如下:
|
||
|
||
```rust
|
||
pub enum Msg {
|
||
InputValue(String),
|
||
}
|
||
```
|
||
|
||
### 使用 `JsCast`
|
||
|
||
[`wasm-bindgen`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/index.html) crate 有一個有用的trait:[`JsCast`](https://rustwasm.github .io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html),它允許我們在類型之間直接轉換,只要它實現了`JsCast` 就行。我們可以謹慎地轉換,這涉及運行時檢查和處理 `Option` 和 `Result` 的邏輯,或者我們也可以冒險直接強行轉換。
|
||
|
||
多說無益,看代碼:
|
||
|
||
```toml title="Cargo.toml"
|
||
[dependencies]
|
||
# 需要 wasm-bindgen 用於呼叫 JsCast
|
||
wasm-bindgen = "0.2"
|
||
```
|
||
|
||
```rust
|
||
//highlight-next-line
|
||
use wasm_bindgen::JsCast;
|
||
use web_sys::{EventTarget, HtmlInputElement};
|
||
use yew::prelude::*;
|
||
|
||
#[function_component]
|
||
fn MyComponent() -> Html {
|
||
let input_value_handle = use_state(String::default);
|
||
let input_value = (*input_value_handle).clone();
|
||
|
||
let on_cautious_change = {
|
||
let input_value_handle = input_value_handle.clone();
|
||
|
||
Callback::from(move |e: Event| {
|
||
// 當事件被建立時,目標是未定義的,只有在派發時才會新增目標。
|
||
let target: Option<EventTarget> = e.target();
|
||
// 事件可能會冒泡,因此此偵聽器可能會捕獲不是 HtmlInputElement 類型的子元素的事件。
|
||
//highlight-next-line
|
||
let input = target.and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
|
||
|
||
if let Some(input) = input {
|
||
input_value_handle.set(input.value());
|
||
}
|
||
})
|
||
};
|
||
|
||
let on_dangerous_change = Callback::from(move |e: Event| {
|
||
let target: EventTarget = e
|
||
.target()
|
||
.expect("Event should have a target when dispatched");
|
||
// 你必須了解 target 是 HtmlInputElement,否則呼叫 value 將是未定義行為(UB)。
|
||
// 在這裡,我們確信這是輸入元素,因此我們可以在不檢查的情況下將其轉換為適當的類型。
|
||
//highlight-next-line
|
||
input_value_handle.set(target.unchecked_into::<HtmlInputElement>().value());
|
||
});
|
||
|
||
html! {
|
||
<>
|
||
<label for="cautious-input">
|
||
{ "My cautious input:" }
|
||
<input onchange={on_cautious_change}
|
||
id="cautious-input"
|
||
type="text"
|
||
value={input_value.clone()}
|
||
/>
|
||
</label>
|
||
<label for="dangerous-input">
|
||
{ "My dangerous input:" }
|
||
<input onchange={on_dangerous_change}
|
||
id="dangerous-input"
|
||
type="text"
|
||
value={input_value}
|
||
/>
|
||
</label>
|
||
</>
|
||
}
|
||
}
|
||
```
|
||
|
||
`JsCast` 提供的方法是 [`dyn_into`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html#method.dyn_into)
|
||
和 [`unchecked_into`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html#method.unchecked_into)。
|
||
如你所見,它們允許我們從 `EventTarget` 轉換為 [`HtmlInputElement`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.HtmlInputElement.html)。
|
||
`dyn_into` 方法是謹慎的,因為它會在運行時檢查類型是否實際為 `HtmlInputElement`,如果不是則返回
|
||
`Err(JsValue)`。 [`JsValue`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html)
|
||
是一個通用類型,將原來的物件回傳給你,以便再次嘗試轉換為別的類型。
|
||
|
||
這會兒你可能會想,什麼時候可以使用危險版本?在上面的情況下,它是安全的<sup>1</sup>,因為我們將 `Callback` 設定在一個沒有子元素的元素上,所以目標只能是同一個元素。
|
||
|
||
_<sup>1</sup> 只要牽涉到 JS 領域,就是安全的。 _
|
||
|
||
### 使用 `TargetCast`
|
||
|
||
**強烈建議先閱讀 [使用 JsCast](#using-jscast)! **
|
||
|
||
:::note
|
||
`TargetCast` 的設計目的是讓新用戶了解 `JsCast` 的行為,但範圍更小,僅涉及事件及其目標。
|
||
|
||
選用 `TargetCast` 或 `JsCast` 純粹是個人偏好,實際您會發現 `TargetCast` 的實作和 `JsCast` 的功能很相似。
|
||
:::
|
||
|
||
`TargetCast` trait 是在 `JsCast` 基礎之上建構的,專門用於從事件中取得類型化的事件目標。
|
||
|
||
`TargetCast` 是 Yew 的一部分,因此無需添加依賴項即可在事件上使用 trait 方法,但它的工作方式與 `JsCast` 非常相似。
|
||
|
||
```rust
|
||
use web_sys::HtmlInputElement;
|
||
use yew::prelude::*;
|
||
|
||
#[function_component]
|
||
fn MyComponent() -> Html {
|
||
let input_value_handle = use_state(String::default);
|
||
let input_value = (*input_value_handle).clone();
|
||
|
||
let on_cautious_change = {
|
||
let input_value_handle = input_value_handle.clone();
|
||
|
||
Callback::from(move |e: Event| {
|
||
let input = e.target_dyn_into::<HtmlInputElement>();
|
||
|
||
if let Some(input) = input {
|
||
input_value_handle.set(input.value());
|
||
}
|
||
})
|
||
};
|
||
|
||
let on_dangerous_change = Callback::from(move |e: Event| {
|
||
// 你必須清楚 target 是 HtmlInputElement,否則呼叫 value 將是未定義行為(UB)。
|
||
//highlight-next-line
|
||
input_value_handle.set(e.target_unchecked_into::<HtmlInputElement>().value());
|
||
});
|
||
|
||
html! {
|
||
<>
|
||
<label for="cautious-input">
|
||
{ "My cautious input:" }
|
||
<input onchange={on_cautious_change}
|
||
id="cautious-input"
|
||
type="text"
|
||
value={input_value.clone()}
|
||
/>
|
||
</label>
|
||
<label for="dangerous-input">
|
||
{ "My dangerous input:" }
|
||
<input onchange={on_dangerous_change}
|
||
id="dangerous-input"
|
||
type="text"
|
||
value={input_value}
|
||
/>
|
||
</label>
|
||
</>
|
||
}
|
||
}
|
||
```
|
||
|
||
如果您已經了解了 `JsCast`,或者了解了這個 trait,您可能會發現 `TargetCast::target_dyn_into` 與 `JsCast::dyn_into` 相似,但專門用於事件的目標。 `TargetCast::target_unchecked_into` 與 `JsCast::unchecked_into` 類似,因此上面關於 `JsCast` 的所有警告都適用於 `TargetCast`。
|
||
|
||
### 使用 `NodeRef`
|
||
|
||
[`NodeRef`](../function-components/node-refs.mdx) 可以取代查詢給定給 `Callback` 的事件。
|
||
|
||
```rust
|
||
use web_sys::HtmlInputElement;
|
||
use yew::prelude::*;
|
||
|
||
#[function_component]
|
||
fn MyComponent() -> Html {
|
||
//highlight-next-line
|
||
let input_node_ref = use_node_ref();
|
||
|
||
let input_value_handle = use_state(String::default);
|
||
let input_value = (*input_value_handle).clone();
|
||
|
||
let onchange = {
|
||
let input_node_ref = input_node_ref.clone();
|
||
|
||
Callback::from(move |_| {
|
||
//highlight-next-line
|
||
let input = input_node_ref.cast::<HtmlInputElement>();
|
||
|
||
if let Some(input) = input {
|
||
input_value_handle.set(input.value());
|
||
}
|
||
})
|
||
};
|
||
|
||
html! {
|
||
<>
|
||
<label for="my-input">
|
||
{ "My input:" }
|
||
//highlight-next-line
|
||
<input ref={input_node_ref}
|
||
{onchange}
|
||
id="my-input"
|
||
type="text"
|
||
value={input_value}
|
||
/>
|
||
</label>
|
||
</>
|
||
}
|
||
}
|
||
```
|
||
|
||
透過 `NodeRef`,你可以忽略事件並使用 `NodeRef::cast` 方法取得一個`Option<HtmlInputElement>` - 這是可選的,因為在設定 `NodeRef` 之前呼叫 `cast`,或者當類型不符時將會回傳 `None`。
|
||
|
||
你可能會看到,透過使用 `NodeRef`,我們不必將 `String` 傳回狀態,因為我們總是存取 `input_node_ref` - 因此我們可以這樣做:
|
||
|
||
```rust
|
||
use web_sys::HtmlInputElement;
|
||
use yew::prelude::*;
|
||
|
||
#[function_component]
|
||
fn MyComponent() -> Html {
|
||
let input_node_ref = use_node_ref();
|
||
|
||
//highlight-start
|
||
let onchange = {
|
||
let input_node_ref = input_node_ref.clone();
|
||
|
||
Callback::from(move |_| {
|
||
if let Some(input) = input_node_ref.cast::<HtmlInputElement>() {
|
||
let value = input.value();
|
||
// 對 value 做點什麼
|
||
}
|
||
})
|
||
};
|
||
//highlight-end
|
||
|
||
html! {
|
||
<>
|
||
<label for="my-input">
|
||
{ "My input:" }
|
||
<input ref={input_node_ref}
|
||
{onchange}
|
||
id="my-input"
|
||
type="text"
|
||
/>
|
||
</label>
|
||
</>
|
||
}
|
||
}
|
||
```
|
||
|
||
您選擇哪種方法取決於您的元件和您的偏好,沒有所謂的*推薦*方法。
|
||
|
||
## 手動事件監聽器
|
||
|
||
您可能想要監聽 Yew 的 `html` 巨集不支援的事件,請查看[這裡列出的支援的事件](#event-types)。
|
||
|
||
為了手動為某個元素新增事件監聽器,我們需要藉助 [`NodeRef`](../function-components/node-refs.mdx),以便在 `use_effect_with` 中使用 [`web-sys`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/index.html) 和 [wasm-bindgen](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/index.html) API 新增監聽器。
|
||
|
||
以下範例將展示如何為虛構的 `custard` 事件新增監聽器。所有不受 yew 支援的事件或自訂事件都可以表示為
|
||
[`web_sys::Event`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html)。如果您需要存取自訂/不受支援事件的特定方法或字段,可以使用
|
||
[`JsCast`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html) 的方法將其轉換為所需的類型。
|
||
|
||
### 使用 `Closure`(冗長版本)
|
||
|
||
直接使用 `web-sys` 和 `wasm-bindgen` 的介面可能有點痛苦…所以要有點心理準備([感謝 `gloo`,有了更簡潔的方法](#using-gloo-concise))。
|
||
|
||
```rust
|
||
use wasm_bindgen::{prelude::Closure, JsCast};
|
||
use web_sys::HtmlElement;
|
||
use yew::prelude::*;
|
||
|
||
#[function_component]
|
||
fn MyComponent() -> Html {
|
||
let div_node_ref = use_node_ref();
|
||
|
||
use_effect_with(
|
||
div_node_ref.clone(),
|
||
{
|
||
let div_node_ref = div_node_ref.clone();
|
||
|
||
move |_| {
|
||
let mut custard_listener = None;
|
||
|
||
if let Some(element) = div_node_ref.cast::<HtmlElement>() {
|
||
// 建立您通常會建立的 Callback
|
||
let oncustard = Callback::from(move |_: Event| {
|
||
// 對 custard 做點什麼..
|
||
});
|
||
|
||
// 從 Box<dyn Fn> 創建一個 Closure - 這必須是 'static
|
||
let listener =
|
||
Closure::<dyn Fn(Event)>::wrap(
|
||
Box::new(move |e: Event| oncustard.emit(e))
|
||
);
|
||
|
||
element
|
||
.add_event_listener_with_callback(
|
||
"custard",
|
||
listener.as_ref().unchecked_ref()
|
||
)
|
||
.unwrap();
|
||
|
||
custard_listener = Some(listener);
|
||
}
|
||
|
||
move || drop(custard_listener)
|
||
}
|
||
}
|
||
);
|
||
|
||
html! {
|
||
<div ref={div_node_ref} id="my-div"></div>
|
||
}
|
||
}
|
||
```
|
||
|
||
有關 `Closure` 的更多信息,請參見 [wasm-bindgen 指南](https://wasm-bindgen.github.io/wasm-bindgen/examples/closures.html)。
|
||
|
||
### 使用 `gloo`(簡潔版本)
|
||
|
||
更方便的方法是使用 `gloo`,更具體地說是 [`gloo_events`](https://docs.rs/gloo-events/0.1.1/gloo_events/index.html),
|
||
它是 `web-sys`、`wasm-bindgen` 的高層抽象實作。
|
||
|
||
`gloo_events` 提供了 `EventListener` 類型,可以用來建立和儲存事件監聽器。
|
||
|
||
```toml title="Cargo.toml"
|
||
[dependencies]
|
||
gloo-events = "0.1"
|
||
```
|
||
|
||
```rust
|
||
use web_sys::HtmlElement;
|
||
use yew::prelude::*;
|
||
|
||
use gloo::events::EventListener;
|
||
|
||
#[function_component]
|
||
fn MyComponent() -> Html {
|
||
let div_node_ref = use_node_ref();
|
||
|
||
use_effect_with(
|
||
div_node_ref.clone(),
|
||
{
|
||
let div_node_ref = div_node_ref.clone();
|
||
|
||
move |_| {
|
||
let mut custard_listener = None;
|
||
|
||
if let Some(element) = div_node_ref.cast::<HtmlElement>() {
|
||
// 建立您通常會建立的 Callback
|
||
let oncustard = Callback::from(move |_: Event| {
|
||
// 對 custard 做點什麼..
|
||
});
|
||
|
||
// 從 Box<dyn Fn> 創建一個 Closure - 這必須是 'static
|
||
let listener = EventListener::new(
|
||
&element,
|
||
"custard",
|
||
move |e| oncustard.emit(e.clone())
|
||
);
|
||
|
||
custard_listener = Some(listener);
|
||
}
|
||
|
||
move || drop(custard_listener)
|
||
}
|
||
}
|
||
);
|
||
|
||
html! {
|
||
<div ref={div_node_ref} id="my-div"></div>
|
||
}
|
||
}
|
||
```
|
||
|
||
有關 `EventListener` 的更多信息,請參見 [gloo_events docs.rs](https://docs.rs/gloo-events/0.1.1/gloo_events/struct.EventListener.html)。
|
||
|
||
## 可用事件的完整清單 {#available-events}
|
||
|
||
| 偵聽器名稱 | `web_sys` 事件類型 |
|
||
| --------------------------- | ------------------------------------------------------------------------------------- |
|
||
| `onabort` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onauxclick` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onblur` | [FocusEvent](https://docs.rs/web-sys/latest/web_sys/struct.FocusEvent.html) |
|
||
| `oncancel` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `oncanplay` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `oncanplaythrough` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onchange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onclick` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onclose` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `oncontextmenu` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `oncuechange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `ondblclick` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `ondrag` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondragend` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondragenter` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondragexit` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondragleave` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondragover` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondragstart` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondrop` | [DragEvent](https://docs.rs/web-sys/latest/web_sys/struct.DragEvent.html) |
|
||
| `ondurationchange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onemptied` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onended` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onerror` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onfocus` | [FocusEvent](https://docs.rs/web-sys/latest/web_sys/struct.FocusEvent.html) |
|
||
| `onfocusin` | [FocusEvent](https://docs.rs/web-sys/latest/web_sys/struct.FocusEvent.html) |
|
||
| `onfocusout` | [FocusEvent](https://docs.rs/web-sys/latest/web_sys/struct.FocusEvent.html) |
|
||
| `onformdata` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `oninput` | [InputEvent](https://docs.rs/web-sys/latest/web_sys/struct.InputEvent.html) |
|
||
| `oninvalid` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onkeydown` | [KeyboardEvent](https://docs.rs/web-sys/latest/web_sys/struct.KeyboardEvent.html) |
|
||
| `onkeypress` | [KeyboardEvent](https://docs.rs/web-sys/latest/web_sys/struct.KeyboardEvent.html) |
|
||
| `onkeyup` | [KeyboardEvent](https://docs.rs/web-sys/latest/web_sys/struct.KeyboardEvent.html) |
|
||
| `onload` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onloadeddata` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onloadedmetadata` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onloadstart` | [ProgressEvent](https://docs.rs/web-sys/latest/web_sys/struct.ProgressEvent.html) |
|
||
| `onmousedown` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onmouseenter` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onmouseleave` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onmousemove` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onmouseout` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onmouseover` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onmouseup` | [MouseEvent](https://docs.rs/web-sys/latest/web_sys/struct.MouseEvent.html) |
|
||
| `onpause` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onplay` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onplaying` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onprogress` | [ProgressEvent](https://docs.rs/web-sys/latest/web_sys/struct.ProgressEvent.html) |
|
||
| `onratechange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onreset` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onresize` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onscroll` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onsecuritypolicyviolation` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onseeked` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onseeking` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onselect` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onslotchange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onstalled` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onsubmit` | [SubmitEvent](https://docs.rs/web-sys/latest/web_sys/struct.SubmitEvent.html) |
|
||
| `onsuspend` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `ontimeupdate` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `ontoggle` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onvolumechange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onwaiting` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onwheel` | [WheelEvent](https://docs.rs/web-sys/latest/web_sys/struct.WheelEvent.html) |
|
||
| `oncopy` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `oncut` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onpaste` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onanimationcancel` | [AnimationEvent](https://docs.rs/web-sys/latest/web_sys/struct.AnimationEvent.html) |
|
||
| `onanimationend` | [AnimationEvent](https://docs.rs/web-sys/latest/web_sys/struct.AnimationEvent.html) |
|
||
| `onanimationiteration` | [AnimationEvent](https://docs.rs/web-sys/latest/web_sys/struct.AnimationEvent.html) |
|
||
| `onanimationstart` | [AnimationEvent](https://docs.rs/web-sys/latest/web_sys/struct.AnimationEvent.html) |
|
||
| `ongotpointercapture` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onloadend` | [ProgressEvent](https://docs.rs/web-sys/latest/web_sys/struct.ProgressEvent.html) |
|
||
| `onlostpointercapture` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointercancel` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerdown` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerenter` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerleave` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerlockchange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onpointerlockerror` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onpointermove` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerout` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerover` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onpointerup` | [PointerEvent](https://docs.rs/web-sys/latest/web_sys/struct.PointerEvent.html) |
|
||
| `onselectionchange` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onselectstart` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `onshow` | [Event](https://docs.rs/web-sys/latest/web_sys/struct.Event.html) |
|
||
| `ontouchcancel` | [TouchEvent](https://docs.rs/web-sys/latest/web_sys/struct.TouchEvent.html) |
|
||
| `ontouchend` | [TouchEvent](https://docs.rs/web-sys/latest/web_sys/struct.TouchEvent.html) |
|
||
| `ontouchmove` | [TouchEvent](https://docs.rs/web-sys/latest/web_sys/struct.TouchEvent.html) |
|
||
| `ontouchstart` | [TouchEvent](https://docs.rs/web-sys/latest/web_sys/struct.TouchEvent.html) |
|
||
| `ontransitioncancel` | [TransitionEvent](https://docs.rs/web-sys/latest/web_sys/struct.TransitionEvent.html) |
|
||
| `ontransitionend` | [TransitionEvent](https://docs.rs/web-sys/latest/web_sys/struct.TransitionEvent.html) |
|
||
| `ontransitionrun` | [TransitionEvent](https://docs.rs/web-sys/latest/web_sys/struct.TransitionEvent.html) |
|
||
| `ontransitionstart` | [TransitionEvent](https://docs.rs/web-sys/latest/web_sys/struct.TransitionEvent.html) |
|