生命週期
Component
trait 有許多方法需要實作;Yew 會在元件的生命週期的不同階段呼叫這些方法。
生命週期
為文件做貢獻:
新增自訂生命週期的組件範例
生命週期方法
Create
當元件被建立時,它會從其父元件接收屬性,並儲存在傳遞給 create
方法的 Context<Self>
中。這些屬性可以用來初始化元件的狀態,而 "link" 可以用來註冊回呼或傳送訊息給元件。
use yew::{Component, Context, html, Html, Properties};
#[derive(PartialEq, Properties)]
pub struct Props;
pub struct MyComponent;
impl Component for MyComponent {
type Message = ();
type Properties = Props;
fn create(ctx: &Context<Self>) -> Self {
MyComponent
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
// 具體實現
}
}
}
View
view
方法可讓您描述元件應該如何呈 現到 DOM 中。使用Rust 函數編寫類似HTML 的程式碼可能會變得非常混亂,因此Yew 提供了一個名為html!
的宏,用於聲明HTML 和SVG 節點(以及將屬性和事件監聽器附加到它們)以及一種方便的方法來渲染子元件。這個宏在某種程度上類似於 React 的 JSX(除了程式語言的差異)。一個不同之處是 Yew 提供了一種類似 Svelte 的屬性的簡寫語法,其中您可以只寫 {onclick}
,而不用寫 onclick={onclick}
。
use yew::{Component, Context, html, Html, Properties};
enum Msg {
Click,
}
#[derive(PartialEq, Properties)]
struct Props {
button_text: String,
}
struct MyComponent;
impl Component for MyComponent {
type Message = Msg;
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
let onclick = ctx.link().callback(|_| Msg::Click);
html! {
<button {onclick}>{ &ctx.props().button_text }</button>
}
}
}
就使用上的說明,請查看 html! 指南。
Rendered
rendered
元件生命週期方法在 view
被調用並且 Yew 已經將結果渲染到 DOM 中後調用,但在瀏覽器刷新頁面之前。當您想要執行只能在元件渲染元素後完成的操作時,此方法非常有用。還有一個名為 first_render
的參數,可以用來確定此函數是在第一次渲染時調用,還是在後續渲染時調用。
use web_sys::HtmlInputElement;
use yew::{
Component, Context, html, Html, NodeRef,
};
pub struct MyComponent {
node_ref: NodeRef,
}
impl Component for MyComponent {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
node_ref: NodeRef::default(),
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<input ref={self.node_ref.clone()} type="text" />
}
}
fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
if first_render {
if let Some(input) = self.node_ref.cast::<HtmlInputElement>() {
input.focus();
}
}
}
}
請注意,此生命週期方法不需要實現,並且預設不會執行任何操作。
Update
與組件的通訊主要透過訊息進行,這些訊息由 update
生命週期方法處理。這允許元件根據訊息更新自身,並確定是否需要重新渲染自身。訊息可以由事件監聽器、子元件、Agents、Services 或 Futures 傳送。
下面是 update
的實作範例:
use yew::{Component, Context, html, Html};
pub enum Msg {
SetInputEnabled(bool)
}
struct MyComponent {
input_enabled: bool,
}
impl Component for MyComponent {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
input_enabled: false,
}
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::SetInputEnabled(enabled) => {
if self.input_enabled != enabled {
self.input_enabled = enabled;
true // 重新渲染
} else {
false
}
}
}
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
// 具體實現
}
}
}
Changed
元件可能會被其父元件重新渲染。當這種情況發生時,它們可能會接收新的屬性並需要重新渲染。這種設計透過僅更改屬性的值來促進父子組件之間的通訊。當屬性更改時,有一個預設實作會重新渲染元件。
Destroy
元件從 DOM 卸載後,Yew 會呼叫 destroy
生命週期方法;如果您需要在元件被銷毀之前執行清理操作,這是必要的。此方法是可選的,預設不執行任何操作。
無限循環
無限循環在 Yew 的生命週期方法中是可能的,但只有在嘗試在每次 渲染後更新相同的元件時,當更新也要求重新渲染元件時才會發生。
下面是一個簡單的範例:
use yew::{Context, Component, Html};
struct Comp;
impl Component for Comp {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> bool {
// 我們總是請求在任何訊息上重新渲染
true
}
fn view(&self, _ctx: &Context<Self>) -> Html {
// 無論渲染什麼都不重要
Html::default()
}
fn rendered(&mut self, ctx: &Context<Self>, _first_render: bool) {
// 請求使用此新訊息更新元件
ctx.link().send_message(());
}
}
讓我們看看這裡發生了什麼:
- 使用
create
函數建立元件。 - 呼叫
view
方法,以便 Yew 知道要渲染到瀏覽器 DOM 中的內容。 - 呼叫
rendered
方法,使用Context
連結安排更新訊息。 - Yew 完成後渲染階段。
- Yew 檢查已排程的事件,並看到更新訊息佇列不為空,因此處理訊息。
- 呼叫
update
方法,回傳true
表示發生了變化,元件需要重新渲染。 - 跳回第 2 步。
您仍然可以在 rendered
方法中安排更新,這通常是有用的,但是在這樣做時,請考慮您的元件將如何終止此循環。
關聯類型
Component
trait 有两个关联类型:Message
和 Properties
。
impl Component for MyComponent {
type Message = Msg;
type Properties = Props;
// ...
}
Message
類型用於在事件發生後向元件發送訊息;例如,您可能希望在使用者點擊按鈕或向下捲動頁面時執行某些操作。因為元件通常需要回應多個事件,所以 Message
類型通常是一個枚舉,其中每個變體都是要處理的事件。
在組織程式碼庫時,將 Message
類型的定義包含在定義元件的相同模組中是明智的。您可能會發現採用一致的命名約定來命名訊息類型很有幫助。一個選項(儘管不是唯一的選項)是將類型命名為 ComponentNameMsg
,例如,如果您的元件名為 Homepage
,則可以將類型命名為 HomepageMsg
。
enum Msg {
Click,
FormInput(String)
}
Properties
表示從其父元件傳遞給元件的訊息。此類型必須實作 Properties
trait(通常透過衍生它)並且可以指定某些屬性是必需的還是可選的。在建立和更新元件時使用此類型。在組件的模組中建立一個名為 Props
的結構體,並將其用作組件的 Properties
類型是一種常見做法。通常將 "properties" 縮寫為 "props"。由於 props 是從父元件傳遞下來的,因此應用程式的根元件通常具有 Properties
類型為 ()
。如果要為根元件指定屬性,請使用 App::mount_with_props
方法。
生命週期上下文
所有組件生命週期方法都接受一個上下文物件。此物件提供了對元件作用域的引用,允許向元件發送訊息並傳遞給元件的 props。