547 lines
29 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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) |