Yew で 「Hello Yew」

wasm-pack を用いた環境構築はできている想定から進めます。できていない場合は、 nju33-com/get-started-wasm をクローンするとすぐ始められます。

Yew インストール

Cargo.tomldependenciesに以下の 1 行を追記します。

yew = { version = "0.14", features = ["web_sys"] }
# ドキュメントを見ると`web_sys`か`std_web`か選べる様ですが、
# `web_sys`の方が`wasm_pack`と同じ人達が作ってるので
# 良いようです

src/lib.rs の編集

行の最初に以下の 1 行を追記しておきます。

#![recursion_limit = "256"]

これは再帰処理回数の制限を増やすためのもので、今回のような簡単なものでは引っかからないですが、かなりすぐ引っかかっるようになってしまうので、事前に書いておきます。

Yew コンポーネントを作る

yew::prelude::*により取り込んだComponentトレイトからコンポーネントを作ります。作る時に最低限やることは以下の通りです。

  1. Message関連型の設定
  2. Properties関連型の設定
  3. create関数の実装
  4. updateメソッドの実装
  5. viewメソッドの実装

色々ありますが、ただ表示テキストを表示したいだけであれば、5 で返すマークアップだけを弄るだけで事足ります。

マークアップもyew::prelude::*から取り込んだhtml!マクロを用いることでほぼ HTMLを書くだけで実装できます。

use yew::prelude::*;

struct MyComponent {}

impl Component for MyComponent {
  type Message = ();
  type Properties = ();
  fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
    Self {}
  }

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

  fn view(&self) -> Html {
    html! {
      <div>{"Hello Yew"}</div>
    }
  }
}

コンポーネントをレンダリングする

yew::initialize()後、上記のコンポーネントをジェネリック型として渡しながらApp::new().mount_to_body()メソッドを呼び出します。これで<body />タグの中にアプリがレンダリングされます。

このような感じでsrc/lib.rsに追記します。

#[wasm_bindgen]
pub fn render_hello() -> Result<(), JsValue> {
  yew::initialize();
  App::<MyComponent>::new().mount_to_body();
  
  Ok(())
}

render_helloと定義したので、これを TypeScript 側(src/main.tsファイル)で呼ぶようにします。

// eslint-disable-next-line @typescript-eslint/no-floating-promises
;(async () => {
  const module = await import('../pkg')
  module.render_hello()
})()

export {}

確認

実行後ブラウザにテキストで「Hello Yew」と表示されれば完了です。動くコードは nju33-com/get-started-yew に置いておきます。