Skip to content

Commit

Permalink
Sync documents
Browse files Browse the repository at this point in the history
  • Loading branch information
langyo committed Oct 17, 2024
1 parent 4ee663b commit 21a0c95
Show file tree
Hide file tree
Showing 56 changed files with 6,325 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
---
title: '子コンポーネント'
---

:::caution

`Children` をチェックおよび操作すると、アプリケーションで驚くべきかつ説明が難しい動作が発生することがよくあります。これにより、エッジケースが発生し、通常は予期しない結果が生じる可能性があります。`Children` を操作しようとする場合は、他の方法を検討する必要があります。

Yew は、子コンポーネントのプロパティの型として `Html` を使用することをサポートしています。`Children` または `ChildrenRenderer` が必要ない場合は、子コンポーネントとして `Html` を使用することをお勧めします。これは `Children` の欠点がなく、パフォーマンスのオーバーヘッドも低くなります。

:::

## 一般的な使用法

_ほとんどの場合、_ コンポーネントに子コンポーネントを持たせる場合、子コンポーネントの型を気にする必要はありません。この場合、以下の例で十分です。

```rust
use yew::{html, Component, Context, Html, Properties};

#[derive(Properties, PartialEq)]
pub struct ListProps {
#[prop_or_default]
pub children: Html,
}

pub struct List;

impl Component for List {
type Message = ();
type Properties = ListProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div class="list">
{ctx.props().children.clone()}
</div>
}
}
}

## 高度な使用法

### 型指定された子コンポーネント

特定のタイプのコンポーネントを子コンポーネントとして渡したい場合は、`yew::html::ChildrenWithProps<T>` を使用できます。

```rust
use yew::{html, ChildrenWithProps, Component, Context, Html, Properties};

pub struct Item;

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

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "item" }
}
}
}

#[derive(Properties, PartialEq)]
pub struct ListProps {
#[prop_or_default]
pub children: ChildrenWithProps<Item>,
}

pub struct List;

impl Component for List {
type Message = ();
type Properties = ListProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div class="list">
{ for ctx.props().children.iter() }
</div>
}
}
}
```

## プロパティを持つネストされた子コンポーネント

コンポーネントがその子コンポーネントを型指定している場合、ネストされたコンポーネントのプロパティにアクセスして変更することができます。

```rust
use std::rc::Rc;
use yew::prelude::*;

#[derive(Clone, PartialEq, Properties)]
pub struct ListItemProps {
value: String,
}

#[function_component]
fn ListItem(props: &ListItemProps) -> Html {
let ListItemProps { value } = props.clone();
html! {
<span>
{value}
</span>
}
}

#[derive(PartialEq, Properties)]
pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}

#[function_component]
fn List(props: &Props) -> Html {
let modified_children = props.children.iter().map(|mut item| {
let mut props = Rc::make_mut(&mut item.props);
props.value = format!("item-{}", props.value);
item
});
html! { for modified_children }
}

html! {
<List>
<ListItem value="a" />
<ListItem value="b" />
<ListItem value="c" />
</List>
};
```

### 列挙型の子コンポーネント

もちろん、時には子コンポーネントをいくつかの異なるコンポーネントに制限する必要がある場合があります。そのような場合には、Yewについてさらに深く理解する必要があります。

ここでは、より良いエルゴノミクスを提供するために [`derive_more`](https://github.com/JelteF/derive_more) を使用しています。使用したくない場合は、各バリアントに対して手動で `From` を実装することができます。

```rust
use yew::{
html, html::ChildrenRenderer, virtual_dom::VChild, Component,
Context, Html, Properties,
};

pub struct Primary;

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

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "Primary" }
}
}
}

pub struct Secondary;

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

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "Secondary" }
}
}
}

#[derive(Clone, derive_more::From, PartialEq)]
pub enum Item {
Primary(VChild<Primary>),
Secondary(VChild<Secondary>),
}

// 現在、`Into<Html>` を実装して、yew が `Item` をどのようにレンダリングするかを知ることができるようにします。
#[allow(clippy::from_over_into)]
impl Into<Html> for Item {
fn into(self) -> Html {
match self {
Self::Primary(child) => child.into(),
Self::Secondary(child) => child.into(),
}
}
}

#[derive(Properties, PartialEq)]
pub struct ListProps {
#[prop_or_default]
pub children: ChildrenRenderer<Item>,
}

pub struct List;

impl Component for List {
type Message = ();
type Properties = ListProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div class="list">
{ for ctx.props().children.iter() }
</div>
}
}
}
```

### オプションの型の子コンポーネント

特定の型の単一のオプションの子コンポーネントを持つこともできます:

```rust
use yew::{
html, html_nested, virtual_dom::VChild, Component,
Context, Html, Properties
};

pub struct PageSideBar;

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

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "sidebar" }
}
}
}

#[derive(Properties, PartialEq)]
pub struct PageProps {
#[prop_or_default]
pub sidebar: Option<VChild<PageSideBar>>,
}

struct Page;

impl Component for Page {
type Message = ();
type Properties = PageProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div class="page">
{ ctx.props().sidebar.clone().map(Html::from).unwrap_or_default() }
// ... ページ内容
</div>
}
}
}

// ページコンポーネントはサイドバーを含むかどうかを選択できます:

pub fn render_page(with_sidebar: bool) -> Html {
if with_sidebar {
// サイドバーを含むページ
html! {
<Page sidebar={html_nested! {
<PageSideBar />
}} />
}
} else {
// サイドバーを含まないページ
html! {
<Page />
}
}
}
```

## さらに読む

- このパターンの実際の例については、yew-router のソースコードを参照してください。より高度な例については、yew リポジトリの[関連する例のリスト](https://github.com/yewstack/yew/tree/master/examples/nested_list)を参照してください。
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: '仕組み'
description: 'フレームワークの低レベルの詳細について'
---

# 基本ライブラリの内部詳細

## `html!` マクロの内部

`html!` マクロは、HTMLに似たカスタム構文で記述されたコードを有効なRustコードに変換します。このマクロを使用することはYewアプリケーションの開発に必須ではありませんが、推奨されています。このマクロが生成するコードはYewのパブリックライブラリAPIを使用しており、希望すれば直接使用することもできます。いくつかのメソッドは意図的に文書化されていないため、誤用を避けるために注意が必要です。`yew-macro`の各更新により、生成されるコードはより効率的になり、`html!`構文をほとんど(または全く)変更することなく破壊的な変更を処理できるようになります。

`html!` マクロを使用すると、宣言的なスタイルでコードを記述できるため、UIレイアウトコードはページのHTMLに非常に似たものになります。アプリケーションがよりインタラクティブになり、コードベースが大きくなるにつれて、この方法はますます有用になります。DOM 操作のすべてのコードを手動で記述するのに比べて、マクロがこれらすべてを処理してくれます。

`html!` マクロの使用は非常に魔法のように感じるかもしれませんが、隠すべきものは何もありません。その仕組みに興味がある場合は、プログラム内の `html!` マクロ呼び出しを展開してみてください。`cargo expand` という便利なコマンドがあり、Rustマクロの展開を確認できます。`cargo expand` はデフォルトで `cargo` に含まれていないため、まだインストールしていない場合は `cargo install cargo-expand` を使用してインストールする必要があります。[Rust-Analyzer](https://rust-analyzer.github.io/)[IDEからマクロ出力を取得するメカニズム](https://rust-analyzer.github.io/manual.html#expand-macro-recursively)を提供しています。

`html!` マクロの出力は通常非常に簡潔です!これは特徴です:機械生成のコードは時々アプリケーション内の他のコードと衝突することがあります。問題を防ぐために、`proc_macro` は「衛生」ルールに従っています。いくつかの例を以下に示します:

1. Yewパッケージを正しく参照するために、マクロ生成コードでは `::yew::<module>` を使用し、直接 `yew::<module>` を使用しません。これは `::alloc::vec::Vec::new()` を呼び出すのと同じ理由です。
2. トレイトメソッド名の衝突を避けるために、`<Type as Trait>` を使用して正しいトレイトメンバーを使用していることを確認します。

## 仮想 DOM とは?

DOM(「ドキュメントオブジェクトモデル」)は、ブラウザによって管理されるHTMLコンテンツの表現です。「仮想」 DOM は、単にメモリ内の DOM のコピーです。仮想 DOM を管理することで、メモリのオーバーヘッドが増加しますが、ブラウザAPIの使用を回避または遅延させることでバッチ処理と高速な読み取りを実現できます。

メモリ内に DOM のコピーを持つことは、宣言的UIを使用するライブラリの使用を促進するのに役立ちます。ユーザーイベントに基づいて DOM を変更するための特定のコードが必要な場合とは異なり、ライブラリは一般的な方法を使用して DOM の「差分」を行うことができます。Yewコンポーネントが更新され、そのレンダリング方法を変更したい場合、Yewライブラリは仮想 DOM の2番目のコピーを構築し、現在画面上に表示されている内容をミラーリングする仮想 DOM と直接比較します。両者の「差分」は増分更新に分解され、ブラウザAPIと共に適用されます。更新が適用されると、古い仮想 DOM のコピーは破棄され、新しいコピーが将来の差分チェックのために保存されます。

この「差分」アルゴリズムは、時間の経過とともに最適化され、複雑なアプリケーションのパフォーマンスを向上させることができます。YewアプリケーションはWebAssemblyを介して実行されるため、Yewは将来的により複雑なアルゴリズムを採用する上で競争力を持つと信じています。

Yewの仮想 DOM はブラウザの DOM と完全に一対一対応しているわけではありません。DOM 要素を整理するための「リスト」や「コンポーネント」も含まれています。リストは単に要素の順序付きリストである場合もありますが、より強力な場合もあります。各リスト要素に「キー」注釈を追加することで、アプリケーション開発者はリストが変更されたときに差分更新の計算に必要な作業量を最小限に抑えるための追加の最適化をYewに提供できます。同様に、コンポーネントは再レンダリングが必要かどうかを示すカスタムロジックを提供し、パフォーマンスを向上させるのに役立ちます。

## Yewスケジューラとコンポーネントスコープのイベントループ

_貢献ドキュメント - `yew::scheduler``yew::html::scope` の仕組みを詳しく説明_

## さらなる読み物

- [Rustのマクロに関する詳細情報](https://doc.rust-lang.org/stable/book/ch19-06-macros.html)
- [`cargo-expand` に関する詳細情報](https://github.com/dtolnay/cargo-expand)
- [`yew::virtual_dom` のAPIドキュメント](https://docs.rs/yew/*/yew/virtual_dom/index.html)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: 'イミュータブルタイプ'
description: 'Yew のイミュータブルデータ構造'
---

## イミュータブルタイプとは?

これらのタイプは、インスタンス化はできるが値を変更することはできないタイプです。値を更新するには、新しい値をインスタンス化する必要があります。

## なぜイミュータブルタイプを使用するのですか?

React と同様に、プロパティは祖先から子孫に伝播されます。これは、各コンポーネントが更新されるたびにプロパティが存在する必要があることを意味します。したがって、プロパティは理想的には簡単にクローンできるべきです。これを実現するために、通常は `Rc` にラップします。

イミュータブルタイプは、コンポーネント間でプロパティの値を低コストでクローンできるため、プロパティの値を保持するのに最適です。

## さらに読む

- [イミュータブルの例](https://github.com/yewstack/yew/tree/master/examples/immutable)
- [Crate `implicit-clone`](https://docs.rs/implicit-clone/)
Loading

0 comments on commit 21a0c95

Please sign in to comment.