EYWによる小道具と入れ子構成要素


これまで、コンポーネントの作成方法と基本的な相互作用の実装方法を学びましたが、コンポーネントシステムの完全なパワーを振るうには、親から子要素への小道具を渡す必要があります.お互いにコンポーネントの入れ子も重要です.
Yewのdevが私の方法に疑問を持ってこなかったので、私はこれを私があなたを教えていないというサインとして見ます、そして、順番に、私はたわごとをしますディー
TL;DR Again, the code can be found on GitHub

セットアップ
私は錆、wasmstra bindgen、またはyewプロジェクトを設定するには行くつもりはない..

メインコンポーネントの作成
我々のアプリのルートコンポーネントから始めましょう.次のコードをあなたのsrc/lib.rs ファイル
#![recursion_limit = "1000"]

mod list;

use list::ListGroup;
use list::ListGroupItem;

use wasm_bindgen::prelude::*;
use yew::prelude::*;

struct Model {}

impl Component for Model {
    type Message = ();
    type Properties = ();

    fn create(_: Self::Properties, _link: ComponentLink<Self>) -> Self {
        Self {}
    }

    fn update(&mut self, _msg: Self::Message) -> ShouldRender {
        false
    }

    fn change(&mut self, _props: Self::Properties) -> ShouldRender {
        false
    }

    fn view(&self) -> Html {
        html! {
            <ListGroup>
                <ListGroupItem>{"First"}</ListGroupItem>
                <ListGroupItem active=true>{"Second"}</ListGroupItem>
                <ListGroupItem>{"Third"}</ListGroupItem>
            </ListGroup>
        }
    }
}

#[wasm_bindgen(start)]
pub fn run_app() {
    App::<Model>::new().mount_to_body();
}
あなたが前の記事を読むならば、そのコードの大部分はよく知られているようでなければなりません、そして、あなたが最近の主要なフロントエンドフレームワークのどれかを最近使用したならばview メソッドは特別に見えません.テキストノードだけがそれらの余分の構文で少しの場所から見えるかもしれません、しかし、どうにか、さびはストリングについて「意見」を持っているようです.
とにかく、トップで、我々は新しいモジュールを宣言しますlist .
The mod list ステートメントには、ファイルにモジュールが存在しますlist.rs , カレントファイルと同じディレクトリにあります.
The use ステートメントでは、現在のファイルで定義されているモジュール内のパブリック値を使用できます.

リストコンポーネントの作成
次に、ルートコンポーネントで使用するコンポーネントを実装する必要があります.このために、作成しましょうsrc/list.rs ファイルを挿入し、このコードを挿入します
use yew::prelude::*;

pub struct ListGroup {
    props: ListGroupProps,
}

#[derive(Properties, Clone)]
pub struct ListGroupProps {
    pub children: Children,
}

impl Component for ListGroup {
    type Message = ();
    type Properties = ListGroupProps;

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

    fn update(&mut self, _msg: Self::Message) -> ShouldRender {
        false
    }

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

    fn view(&self) -> Html {
        html! {
            <ul class="list-group">{ self.props.children.clone() }</ul>
        }
    }
}
それで、ここで何が起こっていますか?
まず、コンポーネントの状態を保持する構造体がprops フィールド.このフィールドは、後に小道具にアクセスするために使用することができますまた、我々は再レンダリングに安全なパフォーマンスをしたいときに古いものに新しい小道具を比較する.
その後、実際に我々の小道具を保持する構造体.この場合、我々は受け入れるだけですchildren 小道具として、何も.ここでstruct定義の上にある属性は、構造体にプレーン構造体では利用できない余分な機能を与えます.これらの特徴は,yewが構造体をprop構造体として認識することが必要である.
次はトレードの実装です.を設定する必要がありますProperties 定義したprop structに型を入力し、いくつかのメソッドを実装します.
最初の興味深い方法はcreate , ここで我々は受信props 我々の州に.
change 我々が同じことをする方法.今回は、小道具が実際に変更されたかどうかを確認できますfalse そうしなければ、再描画を防ぐでしょう.
最後にview メソッド.ここで我々の状態structを取得するself . 状態structが我々のものを持つのでprops そして、順番にprops ホールドchildren , 我々は呼び出すことができますclone() 私たちのコピーを得るためにchildren それはソートされていないリストに表示されます.

項目コンポーネントの作成
リストを保持する必要があります.リストとアイテムコンポーネントが一緒に属しているので、同じファイルに入れましょう.このコードをsrc/list.rs ファイル
pub struct ListGroupItem {
    props: ListGroupItemProps,
}

#[derive(Properties, Clone)]
pub struct ListGroupItemProps {
    pub children: Children,
    #[prop_or(false)]
    pub active: bool,
}

impl Component for ListGroupItem {
    type Message = ();
    type Properties = ListGroupItemProps;

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

    fn update(&mut self, _msg: Self::Message) -> ShouldRender {
        false
    }

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

    fn view(&self) -> Html {
        let mut classes = vec!["list-group-item"];

        if self.props.active {
            classes.push("active")
        }

        html! {
            <li class=classes>{ self.props.children.clone() }</li>
        }
    }
}
項目コンポーネントは、リストコンポーネントとはあまり異なりません.リスト項目のHTML要素をレンダリングし、その子を渡します.
唯一の余分はactive プロップこれにより、異なるスタイルでコンポーネントをマーキングできます.
すべての小道具は、私たちのコンポーネントのユーザーがすべての小道具がどんなタイプを知っている必要があるので、公開されなければなりません.
#[prop_or(false)] 属性は、すべての柱にデフォルト値を与えることができます.あなたがこれを行うことを忘れて、その値を通過しない場合は、行方不明の値とは何もない奇妙なエラーメッセージを取得します.タイプシステムのための「Yay」
view 方法、我々はactive propは条件付きでCSSクラス定義となるベクトルを連結する.
yewは文字列、ベクトル、タプルをclass .

建築&アプリのテスト
アプリケーションを構築するには、次のコマンドを実行します.
$ wasm-pack build --target web --out-name wasm --out-dir ./static
次のコマンドを実行すると、次のようになります.
$ miniserve ./static
And check out your app in the browser!

子供のタイピング
あなたはおそらく考えている、なぜ私たちはchildren もっと具体的な?
まあ、我々はできる!
キャッチオールを使用する代わりにChildren ジェネリック型を使用するChildrenWithProps<T> どこT 項目の型は使用します.
ですから、以下のようにpropsのリストをリファクトしなければなりません.
#[derive(Properties, Clone)]
pub struct ListGroupProps {
    pub children: ChildrenWithProps<ListGroupItem>,
}
この方法では、リストのコンポーネントは、子型としての項目の種類のリストのみを受け取ります.また、コンパイラは、間違った型を使用した場合、ユーザーに警告します.

ボーナス:バイナリサイズ最適化
作成されたWASMバイナリはかなり大きい私のマシンでは、130 KBでした.そこで、ここでいくつかの改善を見てみましょう.
リリースプロファイルをCargo.toml ファイルは、ビットを縮小する必要があります.
[profile.release]
panic = 'abort' 
codegen-units = 1
opt-level = 'z' 
lto = true
また、メモリの割り当てを交換することができます.WAMMコンパイルターゲットに対して明示的に作成されたものがあり、デフォルトのものよりも小さいです.このアロケータはwee_alloc また、依存性として追加することでインストールできますCargo.toml .
[dependencies]
yew = "0.17"
wasm-bindgen = "0.2.67"
wee_alloc = "0.4.2"
そして、あなたの上部にそれを活性化src/lib.rs ファイル.
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
これらの変更の後、私は100 KB、それは約25 %の削減ではなく、偉大な、ひどいではない構築を得た.

結論
ラストはまだおしゃれな感じがしますが、全体的に少なくともYewは私のように反応するdevにとても馴染みがあるようです.
時々、コンパイラのエラーは完全に誤った方向にあなたを導きます、しかし、それはしばしばケースでありません.