Skip to main content
Version: 0.21

元件

什麼是元件?

元件是 Yew 的基石。他們管理自己的狀態,可以渲染自己成為 DOM。元件可以透過實作,描述元件生命周期的 Component trait 來建立。

生命周期

備註

歡迎來貢獻我們的文件: Add a diagram of the component lifecycle

生命周期的方法

Create

當一個元件被建立,他會接收從父元件,也就是 ComponentLink ,傳下來的屬性。 這些屬性用來初始化元件的狀態,此外,「link」可以用來註冊回調函式或傳訊息給元件。

通常,你的元件 struct 會儲存 props 與 link,就像下面的例子:

pub struct MyComponent {
props: Props,
link: ComponentLink<Self>,
}

impl Component for MyComponent {
type Properties = Props;
// ...

fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
MyComponent { props, link }
}

// ...
}

View

元件會在 view() 方法中宣告佈局。Yew 提供 html! 巨集來宣告 HTML 合 SVG 的結點,包含他們的監聽事件與子結點。這個巨集扮演像是 React 的 JSX 的角色,但是是使用 Rust 的表達式,而不是 JavaScript 的。

impl Component for MyComponent {
// ...

fn view(&self) -> Html {
let onclick = self.link.callback(|_| Msg::Click);
html! {
<button {onclick}>{ self.props.button_text }</button>
}
}
}

更多使用細節,請參考 html! 教學

Rendered

rendered() 生命周期的方法會,在 view() 處理完並且 Yew 渲染完你的元件之後,與瀏覽器刷新頁面之前,被呼叫。一個元件可能希望實作這個方法,去執行只能在元件被渲染完元素才能做的事情。 你可以透過 first_render 變數來確認這個元件是不是第一次被渲染。

use stdweb::web::html_element::InputElement;
use stdweb::web::IHtmlElement;
use yew::prelude::*;

pub struct MyComponent {
node_ref: NodeRef,
}

impl Component for MyComponent {
// ...

fn view(&self) -> Html {
html! {
<input ref={self.node_ref.clone()} type="text" />
}
}

fn rendered(&mut self, first_render: bool) {
if first_render {
if let Some(input) = self.node_ref.cast::<InputElement>() {
input.focus();
}
}
}
}
備註

注意,這個生命周期方法,不是一定要被實作,預設的行為是不做任何事情。

Update

元件是可動態更新且可以註冊接收非同步的訊息。 update() 生命周期方法會被每個訊息呼叫。他基於訊息是什麼,來允許元件更新自己,且會決定是否需要重新渲染。 訊息可以被 HTML 元素的監聽器觸發,或被子元件、Agents、Services 或 Futures 傳送。

update() 應用範例:

pub enum Msg {
SetInputEnabled(bool)
}

impl Component for MyComponent {
type Message = Msg;

// ...

fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SetInputEnabled(enabled) => {
if self.input_enabled != enabled {
self.input_enabled = enabled;
true // 重新渲染
} else {
false
}
}
}
}
}

Change

元件可能會被他的父元件重新渲染。當他被父元件重新渲染時,他會收到新的屬性,然後決定要不要再渲染一次。 這設計是讓父元件透過便於跟子元件溝通。

一個簡單的實作方式像:

impl Component for MyComponent {
// ...

fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
}

Destroy

當元件從 DOM 上被解除掛載,Yew 會呼叫 destroy() 生命周期方法以提供任何需要清理的操作。這個方法是不一定要被實作的,預設不會做設任何事。

相關的型別

Component trait 有兩個相關的型別:MessageProperties

impl Component for MyComponent {
type Message = Msg;
type Properties = Props;

// ...
}

Message 負責各式各樣的訊息,他可能被元件處理去觸發各種影響。舉例來說,你可能有一個 Click 的訊息,他會觸發 API 請求,或是切換 UI 元件的樣貌。下面是一個常見的實作,在你的元件模組中,創建一個叫作 Msg 的 enum,然後把他當作元件裡的 Message 型別。通常 message 會縮寫成 msg。

enum Msg {
Click,
}

Properties 代表要從父員件傳遞到子元件的資訊。這個型別必須實作 Properties trait (通常會 deriving 他)並且可以決定某個屬性是必要的屬性,或是可選的屬性。這個型別會在創建元件的時候,或是更新元件的時候被使用到。常見的實作會在你的元件模組中,建立一個叫作 Props 的 struct,然後把他當作元件的Properties 型別。通常 properties 或縮寫成 props。因為屬性是從父原件被傳下來的,所以應用程式中的根元件的 Properties 原則上都是 ()。如果你希望你的根元件有特定的屬性,可以使用 App::mount_with_props 的方法。