ライフサイクル
Component
トレイトには、実装する必要がある多くのメソッドがあります。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
ライフサイクルメソッドによって処理されます。これにより、コンポーネントはメッセージに基づいて自身を更新し、再レンダリングが必要かどうかを判断できます。メッセージはイベントリスナー、子コンポーネント、エージェント、サービス、またはフューチャーによって送信されることがあります。
以下は 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
トレイトには、Message
と Properties
の2つの関連タイプがあります。
impl Component for MyComponent {
type Message = Msg;
type Properties = Props;
// ...
}
Message
タイプは、イベントが発生した後にコンポーネントにメッセージを送信するために使用されます。例えば、ユーザーがボタンをクリックしたり、ページをスクロールしたりしたときに何かを実行したい場合があります。コンポーネントは通常、複数のイベントに応答する必要があるため、Message
タイプは通常、処理するイベントごとにバリアントを持つ列挙型です。
コードベースを整理する際には、Message
タイプの定義をコンポーネントを定義する同じモジュールに含めるのが賢明です。メッセージタイプの命名に一貫した命名規則を採用することが役立つ場合があります。一つのオプション(唯一のオプションではありませんが)は、タイプを ComponentNameMsg
と命名することです。例えば、コンポーネントが Homepage
と名付けられている場合、タイプを HomepageMsg
と命名することができます。
enum Msg {
Click,
FormInput(String)
}
Properties
は、親コンポーネントからコンポーネントに渡される情報を表します。この型は Properties
トレイトを実装する必要があり(通常はそれを派生させる)、特定のプロパティが必須かオプションかを指定できます。コンポーネントの作成および更新時にこの型が使用されます。コンポーネントのモジュール内で Props
という名前の構造体を作成し、それをコンポーネントの Properties
型として使用するのが一般的な方法です。通常、"properties" は "props" と略されます。プロパティは親コ ンポーネントから渡されるため、アプリケーションのルートコンポーネントは通常、Properties
型として ()
を持ちます。ルートコンポーネントにプロパティを指定する場合は、App::mount_with_props
メソッドを使用します。
ライフサイクルコンテキスト
すべてのコンポーネントライフサイクルメソッドは、コンテキストオブジェクトを受け取ります。このオブジェクトは、コンポーネントのスコープへの参照を提供し、コンポーネントにメッセージを送信したり、コンポーネントに渡されたプロパティを取得したりすることができます。