mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
website: add 0.22 to version selector, sync next with 0.22 (#3960)
This commit is contained in:
parent
8211024c24
commit
04a1eb4d49
@ -107,7 +107,7 @@ pub struct ListItemProps {
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn ListItem(props: &ListItemProps) -> Html {
|
||||
let ListItemProps { value } = props.clone();
|
||||
html! {
|
||||
@ -122,7 +122,7 @@ pub struct Props {
|
||||
pub children: ChildrenWithProps<ListItem>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn List(props: &Props) -> Html {
|
||||
let modified_children = props.children.iter().map(|mut item| {
|
||||
let mut props = Rc::make_mut(&mut item.props);
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct ModalProps {
|
||||
pub children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Modal(props: &ModalProps) -> Html {
|
||||
let modal_host = gloo::utils::document()
|
||||
.get_element_by_id("modal_host")
|
||||
|
||||
@ -24,7 +24,7 @@ Yewコンポーネントをサーバーサイドでレンダリングするに
|
||||
use yew::prelude::*;
|
||||
use yew::ServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -112,7 +112,7 @@ SSR出力(静的HTML)をブラウザが初期レンダリングした後、
|
||||
use yew::prelude::*;
|
||||
use yew::Renderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -138,7 +138,7 @@ Yewは `yew::LocalServerRenderer` を使用してシングルスレッドでの
|
||||
use yew::prelude::*;
|
||||
use yew::LocalServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
use yew_router::prelude::*;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ struct Theme {
|
||||
background: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -38,7 +38,7 @@ pub fn App() -> Html {
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButtonHOC() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ description: 'コンテキストを使用して深くネストされたデータ
|
||||
以下の例を考えてみましょう。これは props を介してテーマを渡しています:
|
||||
|
||||
```rust
|
||||
use yew::{html, Component, Context, Html, Properties, function_component};
|
||||
use yew::{html, Component, Context, Html, Properties, component};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Theme {
|
||||
@ -32,7 +32,7 @@ pub struct NavbarProps {
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Navbar(props: &NavbarProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -52,14 +52,14 @@ pub struct ThemeProps {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Title(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn NavButton(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
@ -67,7 +67,7 @@ fn NavButton(_props: &ThemeProps) -> Html {
|
||||
}
|
||||
|
||||
/// アプリのルート
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let theme = Theme {
|
||||
foreground: "yellow".to_owned(),
|
||||
@ -102,7 +102,7 @@ struct Theme {
|
||||
}
|
||||
|
||||
/// メインコンポーネント
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -121,7 +121,7 @@ pub fn App() -> Html {
|
||||
|
||||
/// ツールバー
|
||||
/// このコンポーネントはコンテキストにアクセスできます。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn Toolbar() -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -133,7 +133,7 @@ pub fn Toolbar() -> Html {
|
||||
/// `Toolbar` 内に配置されたボタン
|
||||
/// このコンポーネントは、コンポーネントツリー内の `ThemeContextProvider` の子コンポーネントであるため、
|
||||
/// コンテキストにアクセスできます。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButton() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -22,14 +22,14 @@ let result = cb.emit(String::from("Bob")); // コールバック関数を呼び
|
||||
yew で一般的なパターンは、コールバック関数を作成し、それをプロパティとして子コンポーネントに渡すことです。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub on_name_entry: Callback<String>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
|
||||
props.on_name_entry.emit(String::from("Bob"));
|
||||
@ -38,7 +38,7 @@ fn HelloWorld(props: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 次にプロパティ (Props) を提供します
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let on_name_entry: Callback<String> = Callback::from(move |name: String| {
|
||||
let greeting = format!("Hey, {}!", name);
|
||||
@ -57,9 +57,9 @@ fn App() -> Html {
|
||||
例えば、ここではユーザーがボタンをクリックしたときに呼び出されるコールバック関数を定義します:
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let onclick = Callback::from(move |_| {
|
||||
let greeting = String::from("Hi there");
|
||||
|
||||
@ -5,9 +5,9 @@ title: '子要素 (Children)'
|
||||
`Children` は特別なプロパティタイプで、HTMLの子要素のようにネストされた `Html` を受け取ることができます。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {
|
||||
// highlight-start
|
||||
@ -25,7 +25,7 @@ pub struct Props {
|
||||
pub children: Html, // `children` キーは重要です!
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
html! {
|
||||
<div class="very-stylized-container">
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
---
|
||||
title: 'ジェネリックコンポーネント'
|
||||
description: '関数コンポーネントの #[function_component] 属性'
|
||||
description: '関数コンポーネントの #[component] 属性'
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
`#[function_component]` 属性は、ジェネリックコンポーネントを作成するためのジェネリック関数にも適用されます。
|
||||
`#[component]` 属性は、ジェネリックコンポーネントを作成するためのジェネリック関数にも適用されます。
|
||||
|
||||
```rust
|
||||
use std::fmt::Display;
|
||||
use yew::{function_component, html, Properties, Html};
|
||||
use yew::{component, html, Properties, Html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props<T>
|
||||
@ -20,7 +20,7 @@ where
|
||||
data: T,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||
where
|
||||
T: PartialEq + Clone + Into<Html>,
|
||||
|
||||
@ -15,7 +15,7 @@ use gloo::utils::window;
|
||||
use std::mem::drop;
|
||||
|
||||
|
||||
#[function_component(ShowStorageChanged)]
|
||||
#[component(ShowStorageChanged)]
|
||||
pub fn show_storage_changed() -> Html {
|
||||
let state_storage_changed = use_state(|| false);
|
||||
|
||||
|
||||
@ -27,18 +27,18 @@ slug: /concepts/function-components
|
||||
|
||||
## 関数コンポーネントの作成
|
||||
|
||||
関数コンポーネントを作成するには、関数に `#[function_component]` 属性を追加します。慣例として、関数の名前は PascalCase を使用し、`html!` マクロ内の通常の html 要素と対比させます。
|
||||
関数コンポーネントを作成するには、関数に `#[component]` 属性を追加します。慣例として、関数の名前は PascalCase を使用し、`html!` マクロ内の通常の html 要素と対比させます。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// そして他の場所で、`html!` 内でコンポーネントを使用できます
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
|
||||
@ -43,26 +43,26 @@ pub struct Props {
|
||||
|
||||
## 関数コンポーネントでの使用
|
||||
|
||||
属性 `#[function_component]` は、関数の引数で Props を選択的に受け取ることを可能にします。それらを提供するには、`html!` マクロ内の属性を通じて割り当てることができます。
|
||||
属性 `#[component]` は、関数の引数で Props を選択的に受け取ることを可能にします。それらを提供するには、`html!` マクロ内の属性を通じて割り当てることができます。
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="with-props" label="With Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
html! { <>{"Am I loading? - "}{is_loading}</> }
|
||||
}
|
||||
|
||||
// そしてプロパティを提供します
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -73,15 +73,15 @@ fn App() -> Html {
|
||||
<TabItem value="no-props" label="No Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 提供するプロパティはありません
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
@ -107,7 +107,7 @@ fn App() -> Html {
|
||||
`Default` トレイトを使用して、フィールド型のデフォルト値でプロパティ値を初期化します。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
@ -117,7 +117,7 @@ pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -127,12 +127,12 @@ fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// デフォルト値を使用する
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
// またはデフォルト値を上書きしない
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -158,7 +158,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -168,12 +168,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// デフォルト値を使用する
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// またはデフォルト値を上書きしない
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -202,7 +202,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -212,12 +212,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// デフォルト値を使用する
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// またはデフォルト値を上書きしない
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -251,7 +251,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -260,7 +260,7 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
// highlight-start
|
||||
let pre_made_props = yew::props! {
|
||||
@ -279,9 +279,9 @@ fn App() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_autoprops::autoprops;
|
||||
|
||||
// #[autoprops] マクロは #[function_component] の前に配置する必要があります。順序が重要です。
|
||||
// #[autoprops] マクロは #[component] の前に配置する必要があります。順序が重要です。
|
||||
#[autoprops]
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Greetings(
|
||||
#[prop_or_default]
|
||||
is_loading: bool,
|
||||
|
||||
@ -7,14 +7,14 @@ title: '純粋コンポーネント'
|
||||
この例は純粋コンポーネントです。与えられたプロパティ `is_loading` に対して、常に同じ `Html` を返し、副作用はありません。
|
||||
|
||||
```rust
|
||||
use yew::{Properties, function_component, Html, html};
|
||||
use yew::{Properties, component, Html, html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
if props.is_loading {
|
||||
html! { "Loading" }
|
||||
|
||||
@ -100,7 +100,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent(props: &Props) -> Html {
|
||||
let Props {
|
||||
class,
|
||||
|
||||
@ -10,7 +10,7 @@ description: 'コンポーネント階層を使用して複雑なレイアウト
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
html! {
|
||||
{ "This component has no properties!" }
|
||||
@ -23,7 +23,7 @@ struct Props {
|
||||
user_last_name: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponentWithProps(props: &Props) -> Html {
|
||||
let Props { user_first_name, user_last_name } = props;
|
||||
html! {
|
||||
@ -66,7 +66,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
@ -96,7 +96,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
|
||||
@ -17,7 +17,7 @@ use web_sys::{Element, Node};
|
||||
use yew::prelude::*;
|
||||
use gloo::utils::document;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
// メモ化された関数、一度だけ実行されます
|
||||
let node = use_memo(
|
||||
|
||||
@ -100,7 +100,7 @@ use wasm_bindgen::JsCast;
|
||||
use web_sys::{EventTarget, HtmlInputElement};
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -180,7 +180,7 @@ _<sup>1</sup> JS の領域に関わる限り、安全です。_
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -237,7 +237,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
//highlight-next-line
|
||||
let input_node_ref = use_node_ref();
|
||||
@ -283,7 +283,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_node_ref = use_node_ref();
|
||||
|
||||
@ -334,7 +334,7 @@ use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
use web_sys::HtmlElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
@ -399,7 +399,7 @@ use yew::prelude::*;
|
||||
|
||||
use gloo::events::EventListener;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
|
||||
@ -7,29 +7,28 @@ import TabItem from '@theme/TabItem'
|
||||
|
||||
## イテレータ
|
||||
|
||||
Yew は、イテレータから HTML を構築するための 2 つの異なる構文をサポートしています。
|
||||
イテレータから HTML を構築する方法は 3 つあります:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="Syntax type 1" label="Syntax type 1">
|
||||
|
||||
最初の方法は、イテレータの最終変換で `collect::<Html>()` を呼び出すことで、Yew が表示できるリストを返します。
|
||||
<TabItem value="`for` loops" label="`for` ループ">
|
||||
主なアプローチは for ループを使用することです。これは Rust に既に存在する for ループと同じですが、2 つの重要な違いがあります:
|
||||
1. 通常の for ループは何も返せませんが、`html!` 内の for ループはノードのリストに変換されます。
|
||||
2. `break`、`continue` などの発散式は `html!` 内の for ループの本体では許可されていません。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
for i in 0 .. 10 {
|
||||
<span>{i}</span>
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Syntax type 2" label="Syntax type 2">
|
||||
|
||||
もう一つの方法は、`for` キーワードを使用することです。これはネイティブの Rust 構文ではなく、HTML マクロによってイテレータを表示するために必要なコードを出力します。
|
||||
<TabItem value="`for` block" label="`for` ブロック">
|
||||
もう一つの方法は `for` キーワードを使用することです。これはネイティブの Rust 構文ではなく、HTML マクロによってイテレータを表示するために必要なコードを出力します。
|
||||
この方法は、イテレータが既に計算されていて、マクロに渡すだけでよい場合に最初の方法より適しています。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
@ -41,6 +40,23 @@ html! {
|
||||
{ for items.iter() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="`collect` method" label="`collect` メソッド">
|
||||
|
||||
最後の方法は、イテレータの最終変換で `collect::<Html>()` を呼び出すことで、Yew が表示できるリストを返します。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
@ -59,7 +59,7 @@ enum Route {
|
||||
NotFound,
|
||||
}
|
||||
|
||||
#[function_component(Secure)]
|
||||
#[component(Secure)]
|
||||
fn secure() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -82,7 +82,7 @@ fn switch(routes: Route) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Main)]
|
||||
#[component(Main)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
@ -181,7 +181,7 @@ enum Route {
|
||||
以下は、クリック時に `Home` ルートにナビゲートするボタンを実装する例です。
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(MyComponent)]
|
||||
#[component(MyComponent)]
|
||||
pub fn my_component() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
let onclick = Callback::from(move |_| navigator.push(&Route::Home));
|
||||
@ -206,7 +206,7 @@ pub fn my_component() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[function_component(NavItems)]
|
||||
#[component(NavItems)]
|
||||
pub fn nav_items() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -262,7 +262,7 @@ fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
`yew-router` は prelude に `<Redirect />` コンポーネントも提供しています。これはナビゲーター API と同様の効果を実現するために使用できます。このコンポーネントは、ターゲットルートとして `to` 属性を受け取ります。`<Redirect/>` がレンダリングされると、ユーザーは指定されたルートにリダイレクトされます。以下はその例です:
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(SomePage)]
|
||||
#[component(SomePage)]
|
||||
fn some_page() -> Html {
|
||||
// `use_user` フックを使用してユーザーを取得
|
||||
let user = match use_user() {
|
||||
@ -435,7 +435,7 @@ fn switch_settings(route: SettingsRoute) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
pub fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
|
||||
@ -18,14 +18,14 @@ description: 'データ取得のためのサスペンス'
|
||||
```rust ,ignore
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
@ -116,14 +116,14 @@ fn use_user() -> SuspensionResult<User> {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run, title=main.rs
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let counter = use_state(|| 0);
|
||||
let onclick = {
|
||||
|
||||
@ -26,7 +26,7 @@ description: 'コードエディタの設定'
|
||||
pub struct $Name$Props {
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn $Name$(props: &$Name$Props) -> Html {
|
||||
html! {
|
||||
<$tag$>$END$</$tag$>
|
||||
@ -72,7 +72,7 @@ impl Component for $NAME$ {
|
||||
"#[derive(PartialEq, Properties)]",
|
||||
"pub struct ${1:ComponentName}Props {}",
|
||||
"",
|
||||
"#[function_component]",
|
||||
"#[component]",
|
||||
"pub fn $1(props: &${1}Props) -> Html {",
|
||||
" let ${1}Props {} = props;",
|
||||
" html! {",
|
||||
|
||||
@ -80,7 +80,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run title="src/main.rs"
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<h1>{ "Hello World" }</h1>
|
||||
@ -298,7 +298,7 @@ struct VideosListProps {
|
||||
videos: Vec<Video>,
|
||||
}
|
||||
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
videos.iter().map(|video| html! {
|
||||
<p key={video.id}>{format!("{}: {}", video.speaker, video.title)}</p>
|
||||
@ -327,7 +327,7 @@ struct Video {
|
||||
次に、`VideosList` コンポーネントを使用するように `App` コンポーネントを更新できます。
|
||||
|
||||
```rust ,ignore {4-7,13-14}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
- let videos = videos.iter().map(|video| html! {
|
||||
@ -365,7 +365,7 @@ struct VideosListProps {
|
||||
次に、選択したビデオをコールバックに渡すように `VideosList` コンポーネントを変更します。
|
||||
|
||||
```rust ,ignore {2-4,6-12,15-16}
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
-fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
+fn videos_list(VideosListProps { videos, on_click }: &VideosListProps) -> Html {
|
||||
+ let on_click = on_click.clone();
|
||||
@ -397,7 +397,7 @@ struct VideosDetailsProps {
|
||||
video: Video,
|
||||
}
|
||||
|
||||
#[function_component(VideoDetails)]
|
||||
#[component(VideoDetails)]
|
||||
fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -411,7 +411,7 @@ fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
次に、`App` コンポーネントを変更して、ビデオが選択されたときに `VideoDetails` コンポーネントを表示するようにします。
|
||||
|
||||
```rust ,ignore {4,6-11,13-15,22-23,25-29}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
+ let selected_video = use_state(|| None);
|
||||
@ -500,7 +500,7 @@ struct Video {
|
||||
```rust ,ignore {1,5-25,34-35}
|
||||
+ use gloo_net::http::Request;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
- let videos = vec![
|
||||
- // ...
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"version.label": {
|
||||
"message": "Next",
|
||||
"description": "The label for version current"
|
||||
"description": "The label for version 0.22"
|
||||
},
|
||||
"sidebar.docs.category.Getting Started": {
|
||||
"message": "Getting Started",
|
||||
|
||||
@ -107,7 +107,7 @@ pub struct ListItemProps {
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn ListItem(props: &ListItemProps) -> Html {
|
||||
let ListItemProps { value } = props.clone();
|
||||
html! {
|
||||
@ -122,7 +122,7 @@ pub struct Props {
|
||||
pub children: ChildrenWithProps<ListItem>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn List(props: &Props) -> Html {
|
||||
let modified_children = props.children.iter().map(|mut item| {
|
||||
let mut props = Rc::make_mut(&mut item.props);
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct ModalProps {
|
||||
pub children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Modal(props: &ModalProps) -> Html {
|
||||
let modal_host = gloo::utils::document()
|
||||
.get_element_by_id("modal_host")
|
||||
|
||||
@ -24,7 +24,7 @@ Yewコンポーネントをサーバーサイドでレンダリングするに
|
||||
use yew::prelude::*;
|
||||
use yew::ServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -112,7 +112,7 @@ SSR出力(静的HTML)をブラウザが初期レンダリングした後、
|
||||
use yew::prelude::*;
|
||||
use yew::Renderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -138,7 +138,7 @@ Yewは `yew::LocalServerRenderer` を使用してシングルスレッドでの
|
||||
use yew::prelude::*;
|
||||
use yew::LocalServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
use yew_router::prelude::*;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ struct Theme {
|
||||
background: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -38,7 +38,7 @@ pub fn App() -> Html {
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButtonHOC() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ description: 'コンテキストを使用して深くネストされたデータ
|
||||
以下の例を考えてみましょう。これは props を介してテーマを渡しています:
|
||||
|
||||
```rust
|
||||
use yew::{html, Component, Context, Html, Properties, function_component};
|
||||
use yew::{html, Component, Context, Html, Properties, component};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Theme {
|
||||
@ -32,7 +32,7 @@ pub struct NavbarProps {
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Navbar(props: &NavbarProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -52,14 +52,14 @@ pub struct ThemeProps {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Title(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn NavButton(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
@ -67,7 +67,7 @@ fn NavButton(_props: &ThemeProps) -> Html {
|
||||
}
|
||||
|
||||
/// アプリのルート
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let theme = Theme {
|
||||
foreground: "yellow".to_owned(),
|
||||
@ -102,7 +102,7 @@ struct Theme {
|
||||
}
|
||||
|
||||
/// メインコンポーネント
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -121,7 +121,7 @@ pub fn App() -> Html {
|
||||
|
||||
/// ツールバー
|
||||
/// このコンポーネントはコンテキストにアクセスできます。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn Toolbar() -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -133,7 +133,7 @@ pub fn Toolbar() -> Html {
|
||||
/// `Toolbar` 内に配置されたボタン
|
||||
/// このコンポーネントは、コンポーネントツリー内の `ThemeContextProvider` の子コンポーネントであるため、
|
||||
/// コンテキストにアクセスできます。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButton() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -22,14 +22,14 @@ let result = cb.emit(String::from("Bob")); // コールバック関数を呼び
|
||||
yew で一般的なパターンは、コールバック関数を作成し、それをプロパティとして子コンポーネントに渡すことです。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub on_name_entry: Callback<String>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
|
||||
props.on_name_entry.emit(String::from("Bob"));
|
||||
@ -38,7 +38,7 @@ fn HelloWorld(props: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 次にプロパティ (Props) を提供します
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let on_name_entry: Callback<String> = Callback::from(move |name: String| {
|
||||
let greeting = format!("Hey, {}!", name);
|
||||
@ -57,9 +57,9 @@ fn App() -> Html {
|
||||
例えば、ここではユーザーがボタンをクリックしたときに呼び出されるコールバック関数を定義します:
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let onclick = Callback::from(move |_| {
|
||||
let greeting = String::from("Hi there");
|
||||
|
||||
@ -5,9 +5,9 @@ title: '子要素 (Children)'
|
||||
`Children` は特別なプロパティタイプで、HTMLの子要素のようにネストされた `Html` を受け取ることができます。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {
|
||||
// highlight-start
|
||||
@ -25,7 +25,7 @@ pub struct Props {
|
||||
pub children: Html, // `children` キーは重要です!
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
html! {
|
||||
<div class="very-stylized-container">
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
---
|
||||
title: 'ジェネリックコンポーネント'
|
||||
description: '関数コンポーネントの #[function_component] 属性'
|
||||
description: '関数コンポーネントの #[component] 属性'
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
`#[function_component]` 属性は、ジェネリックコンポーネントを作成するためのジェネリック関数にも適用されます。
|
||||
`#[component]` 属性は、ジェネリックコンポーネントを作成するためのジェネリック関数にも適用されます。
|
||||
|
||||
```rust
|
||||
use std::fmt::Display;
|
||||
use yew::{function_component, html, Properties, Html};
|
||||
use yew::{component, html, Properties, Html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props<T>
|
||||
@ -20,7 +20,7 @@ where
|
||||
data: T,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||
where
|
||||
T: PartialEq + Clone + Into<Html>,
|
||||
|
||||
@ -15,7 +15,7 @@ use gloo::utils::window;
|
||||
use std::mem::drop;
|
||||
|
||||
|
||||
#[function_component(ShowStorageChanged)]
|
||||
#[component(ShowStorageChanged)]
|
||||
pub fn show_storage_changed() -> Html {
|
||||
let state_storage_changed = use_state(|| false);
|
||||
|
||||
|
||||
@ -27,18 +27,18 @@ slug: /concepts/function-components
|
||||
|
||||
## 関数コンポーネントの作成
|
||||
|
||||
関数コンポーネントを作成するには、関数に `#[function_component]` 属性を追加します。慣例として、関数の名前は PascalCase を使用し、`html!` マクロ内の通常の html 要素と対比させます。
|
||||
関数コンポーネントを作成するには、関数に `#[component]` 属性を追加します。慣例として、関数の名前は PascalCase を使用し、`html!` マクロ内の通常の html 要素と対比させます。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// そして他の場所で、`html!` 内でコンポーネントを使用できます
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
|
||||
@ -43,26 +43,26 @@ pub struct Props {
|
||||
|
||||
## 関数コンポーネントでの使用
|
||||
|
||||
属性 `#[function_component]` は、関数の引数で Props を選択的に受け取ることを可能にします。それらを提供するには、`html!` マクロ内の属性を通じて割り当てることができます。
|
||||
属性 `#[component]` は、関数の引数で Props を選択的に受け取ることを可能にします。それらを提供するには、`html!` マクロ内の属性を通じて割り当てることができます。
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="with-props" label="With Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
html! { <>{"Am I loading? - "}{is_loading}</> }
|
||||
}
|
||||
|
||||
// そしてプロパティを提供します
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -73,15 +73,15 @@ fn App() -> Html {
|
||||
<TabItem value="no-props" label="No Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 提供するプロパティはありません
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
@ -107,7 +107,7 @@ fn App() -> Html {
|
||||
`Default` トレイトを使用して、フィールド型のデフォルト値でプロパティ値を初期化します。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
@ -117,7 +117,7 @@ pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -127,12 +127,12 @@ fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// デフォルト値を使用する
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
// またはデフォルト値を上書きしない
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -158,7 +158,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -168,12 +168,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// デフォルト値を使用する
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// またはデフォルト値を上書きしない
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -202,7 +202,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -212,12 +212,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// デフォルト値を使用する
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// またはデフォルト値を上書きしない
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -251,7 +251,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -260,7 +260,7 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
// highlight-start
|
||||
let pre_made_props = yew::props! {
|
||||
@ -279,9 +279,9 @@ fn App() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_autoprops::autoprops;
|
||||
|
||||
// #[autoprops] マクロは #[function_component] の前に配置する必要があります。順序が重要です。
|
||||
// #[autoprops] マクロは #[component] の前に配置する必要があります。順序が重要です。
|
||||
#[autoprops]
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Greetings(
|
||||
#[prop_or_default]
|
||||
is_loading: bool,
|
||||
|
||||
@ -7,14 +7,14 @@ title: '純粋コンポーネント'
|
||||
この例は純粋コンポーネントです。与えられたプロパティ `is_loading` に対して、常に同じ `Html` を返し、副作用はありません。
|
||||
|
||||
```rust
|
||||
use yew::{Properties, function_component, Html, html};
|
||||
use yew::{Properties, component, Html, html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
if props.is_loading {
|
||||
html! { "Loading" }
|
||||
|
||||
@ -100,7 +100,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent(props: &Props) -> Html {
|
||||
let Props {
|
||||
class,
|
||||
|
||||
@ -10,7 +10,7 @@ description: 'コンポーネント階層を使用して複雑なレイアウト
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
html! {
|
||||
{ "This component has no properties!" }
|
||||
@ -23,7 +23,7 @@ struct Props {
|
||||
user_last_name: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponentWithProps(props: &Props) -> Html {
|
||||
let Props { user_first_name, user_last_name } = props;
|
||||
html! {
|
||||
@ -66,7 +66,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
@ -96,7 +96,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
|
||||
@ -17,7 +17,7 @@ use web_sys::{Element, Node};
|
||||
use yew::prelude::*;
|
||||
use gloo::utils::document;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
// メモ化された関数、一度だけ実行されます
|
||||
let node = use_memo(
|
||||
|
||||
@ -100,7 +100,7 @@ use wasm_bindgen::JsCast;
|
||||
use web_sys::{EventTarget, HtmlInputElement};
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -180,7 +180,7 @@ _<sup>1</sup> JS の領域に関わる限り、安全です。_
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -237,7 +237,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
//highlight-next-line
|
||||
let input_node_ref = use_node_ref();
|
||||
@ -283,7 +283,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_node_ref = use_node_ref();
|
||||
|
||||
@ -334,7 +334,7 @@ use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
use web_sys::HtmlElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
@ -399,7 +399,7 @@ use yew::prelude::*;
|
||||
|
||||
use gloo::events::EventListener;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
|
||||
@ -7,29 +7,28 @@ import TabItem from '@theme/TabItem'
|
||||
|
||||
## イテレータ
|
||||
|
||||
Yew は、イテレータから HTML を構築するための 2 つの異なる構文をサポートしています。
|
||||
イテレータから HTML を構築する方法は 3 つあります:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="Syntax type 1" label="Syntax type 1">
|
||||
|
||||
最初の方法は、イテレータの最終変換で `collect::<Html>()` を呼び出すことで、Yew が表示できるリストを返します。
|
||||
<TabItem value="`for` loops" label="`for` ループ">
|
||||
主なアプローチは for ループを使用することです。これは Rust に既に存在する for ループと同じですが、2 つの重要な違いがあります:
|
||||
1. 通常の for ループは何も返せませんが、`html!` 内の for ループはノードのリストに変換されます。
|
||||
2. `break`、`continue` などの発散式は `html!` 内の for ループの本体では許可されていません。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
for i in 0 .. 10 {
|
||||
<span>{i}</span>
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Syntax type 2" label="Syntax type 2">
|
||||
|
||||
もう一つの方法は、`for` キーワードを使用することです。これはネイティブの Rust 構文ではなく、HTML マクロによってイテレータを表示するために必要なコードを出力します。
|
||||
<TabItem value="`for` block" label="`for` ブロック">
|
||||
もう一つの方法は `for` キーワードを使用することです。これはネイティブの Rust 構文ではなく、HTML マクロによってイテレータを表示するために必要なコードを出力します。
|
||||
この方法は、イテレータが既に計算されていて、マクロに渡すだけでよい場合に最初の方法より適しています。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
@ -41,6 +40,23 @@ html! {
|
||||
{ for items.iter() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="`collect` method" label="`collect` メソッド">
|
||||
|
||||
最後の方法は、イテレータの最終変換で `collect::<Html>()` を呼び出すことで、Yew が表示できるリストを返します。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
@ -59,7 +59,7 @@ enum Route {
|
||||
NotFound,
|
||||
}
|
||||
|
||||
#[function_component(Secure)]
|
||||
#[component(Secure)]
|
||||
fn secure() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -82,7 +82,7 @@ fn switch(routes: Route) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Main)]
|
||||
#[component(Main)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
@ -181,7 +181,7 @@ enum Route {
|
||||
以下は、クリック時に `Home` ルートにナビゲートするボタンを実装する例です。
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(MyComponent)]
|
||||
#[component(MyComponent)]
|
||||
pub fn my_component() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
let onclick = Callback::from(move |_| navigator.push(&Route::Home));
|
||||
@ -206,7 +206,7 @@ pub fn my_component() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[function_component(NavItems)]
|
||||
#[component(NavItems)]
|
||||
pub fn nav_items() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -262,7 +262,7 @@ fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
`yew-router` は prelude に `<Redirect />` コンポーネントも提供しています。これはナビゲーター API と同様の効果を実現するために使用できます。このコンポーネントは、ターゲットルートとして `to` 属性を受け取ります。`<Redirect/>` がレンダリングされると、ユーザーは指定されたルートにリダイレクトされます。以下はその例です:
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(SomePage)]
|
||||
#[component(SomePage)]
|
||||
fn some_page() -> Html {
|
||||
// `use_user` フックを使用してユーザーを取得
|
||||
let user = match use_user() {
|
||||
@ -435,7 +435,7 @@ fn switch_settings(route: SettingsRoute) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
pub fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
|
||||
@ -18,14 +18,14 @@ description: 'データ取得のためのサスペンス'
|
||||
```rust ,ignore
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
@ -116,14 +116,14 @@ fn use_user() -> SuspensionResult<User> {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run, title=main.rs
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let counter = use_state(|| 0);
|
||||
let onclick = {
|
||||
|
||||
@ -26,7 +26,7 @@ description: 'コードエディタの設定'
|
||||
pub struct $Name$Props {
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn $Name$(props: &$Name$Props) -> Html {
|
||||
html! {
|
||||
<$tag$>$END$</$tag$>
|
||||
@ -72,7 +72,7 @@ impl Component for $NAME$ {
|
||||
"#[derive(PartialEq, Properties)]",
|
||||
"pub struct ${1:ComponentName}Props {}",
|
||||
"",
|
||||
"#[function_component]",
|
||||
"#[component]",
|
||||
"pub fn $1(props: &${1}Props) -> Html {",
|
||||
" let ${1}Props {} = props;",
|
||||
" html! {",
|
||||
|
||||
@ -80,7 +80,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run title="src/main.rs"
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<h1>{ "Hello World" }</h1>
|
||||
@ -298,7 +298,7 @@ struct VideosListProps {
|
||||
videos: Vec<Video>,
|
||||
}
|
||||
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
videos.iter().map(|video| html! {
|
||||
<p key={video.id}>{format!("{}: {}", video.speaker, video.title)}</p>
|
||||
@ -327,7 +327,7 @@ struct Video {
|
||||
次に、`VideosList` コンポーネントを使用するように `App` コンポーネントを更新できます。
|
||||
|
||||
```rust ,ignore {4-7,13-14}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
- let videos = videos.iter().map(|video| html! {
|
||||
@ -365,7 +365,7 @@ struct VideosListProps {
|
||||
次に、選択したビデオをコールバックに渡すように `VideosList` コンポーネントを変更します。
|
||||
|
||||
```rust ,ignore {2-4,6-12,15-16}
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
-fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
+fn videos_list(VideosListProps { videos, on_click }: &VideosListProps) -> Html {
|
||||
+ let on_click = on_click.clone();
|
||||
@ -397,7 +397,7 @@ struct VideosDetailsProps {
|
||||
video: Video,
|
||||
}
|
||||
|
||||
#[function_component(VideoDetails)]
|
||||
#[component(VideoDetails)]
|
||||
fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -411,7 +411,7 @@ fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
次に、`App` コンポーネントを変更して、ビデオが選択されたときに `VideoDetails` コンポーネントを表示するようにします。
|
||||
|
||||
```rust ,ignore {4,6-11,13-15,22-23,25-29}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
+ let selected_video = use_state(|| None);
|
||||
@ -500,7 +500,7 @@ struct Video {
|
||||
```rust ,ignore {1,5-25,34-35}
|
||||
+ use gloo_net::http::Request;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
- let videos = vec![
|
||||
- // ...
|
||||
|
||||
@ -108,7 +108,7 @@ pub struct ListItemProps {
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn ListItem(props: &ListItemProps) -> Html {
|
||||
let ListItemProps { value } = props.clone();
|
||||
html! {
|
||||
@ -123,7 +123,7 @@ pub struct Props {
|
||||
pub children: ChildrenWithProps<ListItem>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn List(props: &Props) -> Html {
|
||||
let modified_children = props.children.iter().map(|mut item| {
|
||||
let mut props = Rc::make_mut(&mut item.props);
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct ModalProps {
|
||||
pub children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Modal(props: &ModalProps) -> Html {
|
||||
let modal_host = gloo::utils::document()
|
||||
.get_element_by_id("modal_host")
|
||||
|
||||
@ -24,7 +24,7 @@ Yew 提供了一个 `ServerRenderer` 来在服务端渲染页面。
|
||||
use yew::prelude::*;
|
||||
use yew::ServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -112,7 +112,7 @@ Yew 采用了一种不同的方法,通过 `<Suspense />` 来解决这个问题
|
||||
use yew::prelude::*;
|
||||
use yew::Renderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -138,7 +138,7 @@ Yew 支持以单线程进行服务端渲染,通过 `yew::LocalServerRenderer`
|
||||
use yew::prelude::*;
|
||||
use yew::LocalServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
use yew_router::prelude::*;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ struct Theme {
|
||||
background: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -38,7 +38,7 @@ pub fn App() -> Html {
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButtonHOC() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ description: '使用上下文传递深度嵌套数据'
|
||||
考虑以下示例,它通过 props 传递主题:
|
||||
|
||||
```rust
|
||||
use yew::{html, Component, Context, Html, Properties, function_component};
|
||||
use yew::{html, Component, Context, Html, Properties, component};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Theme {
|
||||
@ -32,7 +32,7 @@ pub struct NavbarProps {
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Navbar(props: &NavbarProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -52,14 +52,14 @@ pub struct ThemeProps {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Title(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn NavButton(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
@ -67,7 +67,7 @@ fn NavButton(_props: &ThemeProps) -> Html {
|
||||
}
|
||||
|
||||
/// App 根节点
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let theme = Theme {
|
||||
foreground: "yellow".to_owned(),
|
||||
@ -103,7 +103,7 @@ struct Theme {
|
||||
}
|
||||
|
||||
/// 主组件
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -122,7 +122,7 @@ pub fn App() -> Html {
|
||||
|
||||
/// 工具栏
|
||||
/// 此组件可以访问上下文。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn Toolbar() -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -133,7 +133,7 @@ pub fn Toolbar() -> Html {
|
||||
|
||||
/// 放置在 `Toolbar` 中的按钮
|
||||
/// 由于此组件是组件树中 `ThemeContextProvider` 的子组件,它也可以访问上下文。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButton() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -22,14 +22,14 @@ let result = cb.emit(String::from("Bob")); // 调用回调函数
|
||||
在 yew 中的一个常见模式是创建一个回调函数,并将其作为属性传递给子组件。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub on_name_entry: Callback<String>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
|
||||
props.on_name_entry.emit(String::from("Bob"));
|
||||
@ -38,7 +38,7 @@ fn HelloWorld(props: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 然后提供属性 (Props)
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let on_name_entry: Callback<String> = Callback::from(move |name: String| {
|
||||
let greeting = format!("Hey, {}!", name);
|
||||
@ -57,9 +57,9 @@ fn App() -> Html {
|
||||
例如,这里我们定义了一个回调函数,当用户点击按钮时将会调用:
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let onclick = Callback::from(move |_| {
|
||||
let greeting = String::from("Hi there");
|
||||
|
||||
@ -5,9 +5,9 @@ title: '子元素 (Children)'
|
||||
`Children` 是一种特殊的属性类型,允许您接收嵌套的 `Html`,就像 html 子元素一样提供。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {
|
||||
// highlight-start
|
||||
@ -25,7 +25,7 @@ pub struct Props {
|
||||
pub children: Html, // `children` 键很重要!
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
html! {
|
||||
<div class="very-stylized-container">
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
---
|
||||
title: '泛型组件'
|
||||
description: '函数组件的 #[function_component] 属性'
|
||||
description: '函数组件的 #[component] 属性'
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
`#[function_component]` 属性也适用于用于创建泛型组件的泛型函数。
|
||||
`#[component]` 属性也适用于用于创建泛型组件的泛型函数。
|
||||
|
||||
```rust
|
||||
use std::fmt::Display;
|
||||
use yew::{function_component, html, Properties, Html};
|
||||
use yew::{component, html, Properties, Html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props<T>
|
||||
@ -20,7 +20,7 @@ where
|
||||
data: T,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||
where
|
||||
T: PartialEq + Clone + Into<Html>,
|
||||
|
||||
@ -15,7 +15,7 @@ use gloo::utils::window;
|
||||
use std::mem::drop;
|
||||
|
||||
|
||||
#[function_component(ShowStorageChanged)]
|
||||
#[component(ShowStorageChanged)]
|
||||
pub fn show_storage_changed() -> Html {
|
||||
let state_storage_changed = use_state(|| false);
|
||||
|
||||
|
||||
@ -27,18 +27,18 @@ slug: /concepts/function-components
|
||||
|
||||
## 创建函数组件
|
||||
|
||||
要创建一个函数组件,请将 `#[function_component]` 属性添加到一个函数中。按照惯例,函数的名称采用 PascalCase,与 `html!` 宏中的普通 html 元素形成对比。
|
||||
要创建一个函数组件,请将 `#[component]` 属性添加到一个函数中。按照惯例,函数的名称采用 PascalCase,与 `html!` 宏中的普通 html 元素形成对比。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 然后在其他地方,您可以在 `html!` 中使用组件
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
|
||||
@ -43,26 +43,26 @@ pub struct Props {
|
||||
|
||||
## 在函数组件中使用
|
||||
|
||||
属性 `#[function_component]` 允许在函数参数中选择性地接收 Props。要提供它们,可以通过 `html!` 宏中的属性进行赋值。
|
||||
属性 `#[component]` 允许在函数参数中选择性地接收 Props。要提供它们,可以通过 `html!` 宏中的属性进行赋值。
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="with-props" label="With Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
html! { <>{"Am I loading? - "}{is_loading}</> }
|
||||
}
|
||||
|
||||
// 然后提供属性
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -73,15 +73,15 @@ fn App() -> Html {
|
||||
<TabItem value="no-props" label="No Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 没有属性需要提供
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
@ -107,7 +107,7 @@ fn App() -> Html {
|
||||
使用 `Default` trait 的字段类型的默认值初始化属性值。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
@ -117,7 +117,7 @@ pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -127,12 +127,12 @@ fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 这样使用默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
// 或者不覆盖默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -158,7 +158,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -168,12 +168,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 这样使用默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// 或者不覆盖默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -202,7 +202,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -212,12 +212,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 使用默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// 或者不覆盖默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -251,7 +251,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -260,7 +260,7 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
// highlight-start
|
||||
let pre_made_props = yew::props! {
|
||||
@ -279,9 +279,9 @@ fn App() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_autoprops::autoprops;
|
||||
|
||||
// #[autoprops] 宏必须出现在 #[function_component] 之前,顺序很重要
|
||||
// #[autoprops] 宏必须出现在 #[component] 之前,顺序很重要
|
||||
#[autoprops]
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Greetings(
|
||||
#[prop_or_default]
|
||||
is_loading: bool,
|
||||
|
||||
@ -7,14 +7,14 @@ title: '纯组件'
|
||||
这个例子是一个纯组件。对于给定的属性 `is_loading`,它总是返回相同的 `Html`,没有任何副作用。
|
||||
|
||||
```rust
|
||||
use yew::{Properties, function_component, Html, html};
|
||||
use yew::{Properties, component, Html, html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
if props.is_loading {
|
||||
html! { "Loading" }
|
||||
|
||||
@ -100,7 +100,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent(props: &Props) -> Html {
|
||||
let Props {
|
||||
class,
|
||||
|
||||
@ -10,7 +10,7 @@ description: '使用组件层次结构创建复杂的布局'
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
html! {
|
||||
{ "This component has no properties!" }
|
||||
@ -23,7 +23,7 @@ struct Props {
|
||||
user_last_name: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponentWithProps(props: &Props) -> Html {
|
||||
let Props { user_first_name, user_last_name } = props;
|
||||
html! {
|
||||
@ -66,7 +66,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
@ -96,7 +96,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
|
||||
@ -17,7 +17,7 @@ use web_sys::{Element, Node};
|
||||
use yew::prelude::*;
|
||||
use gloo::utils::document;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
// 带记忆能力的函数,只会执行一次
|
||||
let node = use_memo(
|
||||
|
||||
@ -100,7 +100,7 @@ use wasm_bindgen::JsCast;
|
||||
use web_sys::{EventTarget, HtmlInputElement};
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -183,7 +183,7 @@ _<sup>1</sup> 只要涉及到 JS 领域,就是安全的。_
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -239,7 +239,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
//highlight-next-line
|
||||
let input_node_ref = use_node_ref();
|
||||
@ -285,7 +285,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_node_ref = use_node_ref();
|
||||
|
||||
@ -338,7 +338,7 @@ use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
use web_sys::HtmlElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
@ -403,7 +403,7 @@ use yew::prelude::*;
|
||||
|
||||
use gloo::events::EventListener;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
|
||||
@ -7,29 +7,28 @@ import TabItem from '@theme/TabItem'
|
||||
|
||||
## 迭代器
|
||||
|
||||
Yew 支持两种不同的语法来从迭代器构建 HTML。
|
||||
从迭代器构建 HTML 有 3 种方法:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="Syntax type 1" label="Syntax type 1">
|
||||
|
||||
第一种方法是在迭代器的最终转换上调用 `collect::<Html>()`,它返回一个 Yew 可以显示的列表。
|
||||
<TabItem value="`for` loops" label="`for` 循环">
|
||||
主要方法是使用 for 循环,与 Rust 中已有的 for 循环相同,但有 2 个关键区别:
|
||||
1. 与标准 for 循环不能返回任何内容不同,`html!` 中的 for 循环会被转换为节点列表;
|
||||
2. 发散表达式,即 `break`、`continue` 在 `html!` 中的 for 循环体内是不允许的。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
for i in 0 .. 10 {
|
||||
<span>{i}</span>
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Syntax type 2" label="Syntax type 2">
|
||||
|
||||
<TabItem value="`for` block" label="`for` 块">
|
||||
另一种方法是使用 `for` 关键字,这不是原生的 Rust 语法,而是由 HTML 宏用于输出显示迭代器所需的代码。
|
||||
当迭代器已经计算好,只需要将其传递给宏时,这种方法比第一种更好。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
@ -41,6 +40,23 @@ html! {
|
||||
{ for items.iter() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="`collect` method" label="`collect` 方法">
|
||||
|
||||
最后一种方法是在迭代器的最终转换上调用 `collect::<Html>()`,它返回一个 Yew 可以显示的列表。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
@ -59,7 +59,7 @@ enum Route {
|
||||
NotFound,
|
||||
}
|
||||
|
||||
#[function_component(Secure)]
|
||||
#[component(Secure)]
|
||||
fn secure() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -82,7 +82,7 @@ fn switch(routes: Route) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Main)]
|
||||
#[component(Main)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
@ -181,7 +181,7 @@ enum Route {
|
||||
以下是实现一个按钮的示例,该按钮在点击时导航到 `Home` 路由。
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(MyComponent)]
|
||||
#[component(MyComponent)]
|
||||
pub fn my_component() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
let onclick = Callback::from(move |_| navigator.push(&Route::Home));
|
||||
@ -206,7 +206,7 @@ pub fn my_component() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[function_component(NavItems)]
|
||||
#[component(NavItems)]
|
||||
pub fn nav_items() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -262,7 +262,7 @@ fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
`yew-router` 还在 prelude 中提供了一个 `<Redirect />` 组件。它可以用于实现与导航器 API 类似的效果。该组件接受一个 `to` 属性作为目标路由。当渲染 `<Redirect/>` 时,用户将被重定向到属性中指定的路由。以下是一个示例:
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(SomePage)]
|
||||
#[component(SomePage)]
|
||||
fn some_page() -> Html {
|
||||
// 建立对 `use_user` 的钩子
|
||||
let user = match use_user() {
|
||||
@ -435,7 +435,7 @@ fn switch_settings(route: SettingsRoute) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
pub fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
|
||||
@ -18,14 +18,14 @@ description: '用于数据获取的占位标签'
|
||||
```rust ,ignore
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
@ -116,14 +116,14 @@ fn use_user() -> SuspensionResult<User> {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run, title=main.rs
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let counter = use_state(|| 0);
|
||||
let onclick = {
|
||||
|
||||
@ -26,7 +26,7 @@ description: '设置您的代码编辑器'
|
||||
pub struct $Name$Props {
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn $Name$(props: &$Name$Props) -> Html {
|
||||
html! {
|
||||
<$tag$>$END$</$tag$>
|
||||
@ -72,7 +72,7 @@ impl Component for $NAME$ {
|
||||
"#[derive(PartialEq, Properties)]",
|
||||
"pub struct ${1:ComponentName}Props {}",
|
||||
"",
|
||||
"#[function_component]",
|
||||
"#[component]",
|
||||
"pub fn $1(props: &${1}Props) -> Html {",
|
||||
" let ${1}Props {} = props;",
|
||||
" html! {",
|
||||
|
||||
@ -80,7 +80,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run title="src/main.rs"
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<h1>{ "Hello World" }</h1>
|
||||
@ -298,7 +298,7 @@ struct VideosListProps {
|
||||
videos: Vec<Video>,
|
||||
}
|
||||
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
videos.iter().map(|video| html! {
|
||||
<p key={video.id}>{format!("{}: {}", video.speaker, video.title)}</p>
|
||||
@ -327,7 +327,7 @@ struct Video {
|
||||
现在,我们可以更新我们的 `App` 组件以使用 `VideosList` 组件。
|
||||
|
||||
```rust ,ignore {4-7,13-14}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
- let videos = videos.iter().map(|video| html! {
|
||||
@ -365,7 +365,7 @@ struct VideosListProps {
|
||||
然后我们修改 `VideosList` 组件以将所选视频传递给回调。
|
||||
|
||||
```rust ,ignore {2-4,6-12,15-16}
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
-fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
+fn videos_list(VideosListProps { videos, on_click }: &VideosListProps) -> Html {
|
||||
+ let on_click = on_click.clone();
|
||||
@ -397,7 +397,7 @@ struct VideosDetailsProps {
|
||||
video: Video,
|
||||
}
|
||||
|
||||
#[function_component(VideoDetails)]
|
||||
#[component(VideoDetails)]
|
||||
fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -411,7 +411,7 @@ fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
现在,修改 `App` 组件以在选择视频时显示 `VideoDetails` 组件。
|
||||
|
||||
```rust ,ignore {4,6-11,13-15,22-23,25-29}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
+ let selected_video = use_state(|| None);
|
||||
@ -500,7 +500,7 @@ struct Video {
|
||||
```rust ,ignore {1,5-25,34-35}
|
||||
+ use gloo_net::http::Request;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
- let videos = vec![
|
||||
- // ...
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"version.label": {
|
||||
"message": "Next",
|
||||
"description": "The label for version current"
|
||||
"description": "The label for version 0.22"
|
||||
},
|
||||
"sidebar.docs.category.Getting Started": {
|
||||
"message": "从零开始",
|
||||
@ -83,4 +83,4 @@
|
||||
"message": "结构化组件",
|
||||
"description": "The label for category Struct Components in sidebar docs"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ pub struct ListItemProps {
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn ListItem(props: &ListItemProps) -> Html {
|
||||
let ListItemProps { value } = props.clone();
|
||||
html! {
|
||||
@ -123,7 +123,7 @@ pub struct Props {
|
||||
pub children: ChildrenWithProps<ListItem>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn List(props: &Props) -> Html {
|
||||
let modified_children = props.children.iter().map(|mut item| {
|
||||
let mut props = Rc::make_mut(&mut item.props);
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct ModalProps {
|
||||
pub children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Modal(props: &ModalProps) -> Html {
|
||||
let modal_host = gloo::utils::document()
|
||||
.get_element_by_id("modal_host")
|
||||
|
||||
@ -24,7 +24,7 @@ Yew 提供了一个 `ServerRenderer` 来在服务端渲染页面。
|
||||
use yew::prelude::*;
|
||||
use yew::ServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -112,7 +112,7 @@ Yew 采用了一种不同的方法,通过 `<Suspense />` 来解决这个问题
|
||||
use yew::prelude::*;
|
||||
use yew::Renderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -138,7 +138,7 @@ Yew 支持以单线程进行服务端渲染,通过 `yew::LocalServerRenderer`
|
||||
use yew::prelude::*;
|
||||
use yew::LocalServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
use yew_router::prelude::*;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ struct Theme {
|
||||
background: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -38,7 +38,7 @@ pub fn App() -> Html {
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButtonHOC() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ description: '使用上下文传递深度嵌套数据'
|
||||
考虑以下示例,它通过 props 传递主题:
|
||||
|
||||
```rust
|
||||
use yew::{html, Component, Context, Html, Properties, function_component};
|
||||
use yew::{html, Component, Context, Html, Properties, component};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Theme {
|
||||
@ -32,7 +32,7 @@ pub struct NavbarProps {
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Navbar(props: &NavbarProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -52,14 +52,14 @@ pub struct ThemeProps {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Title(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn NavButton(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
@ -67,7 +67,7 @@ fn NavButton(_props: &ThemeProps) -> Html {
|
||||
}
|
||||
|
||||
/// App 根节点
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let theme = Theme {
|
||||
foreground: "yellow".to_owned(),
|
||||
@ -103,7 +103,7 @@ struct Theme {
|
||||
}
|
||||
|
||||
/// 主组件
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -122,7 +122,7 @@ pub fn App() -> Html {
|
||||
|
||||
/// 工具栏
|
||||
/// 此组件可以访问上下文。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn Toolbar() -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -133,7 +133,7 @@ pub fn Toolbar() -> Html {
|
||||
|
||||
/// 放置在 `Toolbar` 中的按钮
|
||||
/// 由于此组件是组件树中 `ThemeContextProvider` 的子组件,它也可以访问上下文。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButton() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -22,14 +22,14 @@ let result = cb.emit(String::from("Bob")); // 调用回调函数
|
||||
在 yew 中的一个常见模式是创建一个回调函数,并将其作为属性传递给子组件。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub on_name_entry: Callback<String>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
|
||||
props.on_name_entry.emit(String::from("Bob"));
|
||||
@ -38,7 +38,7 @@ fn HelloWorld(props: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 然后提供属性 (Props)
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let on_name_entry: Callback<String> = Callback::from(move |name: String| {
|
||||
let greeting = format!("Hey, {}!", name);
|
||||
@ -57,9 +57,9 @@ fn App() -> Html {
|
||||
例如,这里我们定义了一个回调函数,当用户点击按钮时将会调用:
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let onclick = Callback::from(move |_| {
|
||||
let greeting = String::from("Hi there");
|
||||
|
||||
@ -5,9 +5,9 @@ title: '子元素 (Children)'
|
||||
`Children` 是一种特殊的属性类型,允许您接收嵌套的 `Html`,就像 html 子元素一样提供。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {
|
||||
// highlight-start
|
||||
@ -25,7 +25,7 @@ pub struct Props {
|
||||
pub children: Html, // `children` 键很重要!
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
html! {
|
||||
<div class="very-stylized-container">
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
---
|
||||
title: '泛型组件'
|
||||
description: '函数组件的 #[function_component] 属性'
|
||||
description: '函数组件的 #[component] 属性'
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
`#[function_component]` 属性也适用于用于创建泛型组件的泛型函数。
|
||||
`#[component]` 属性也适用于用于创建泛型组件的泛型函数。
|
||||
|
||||
```rust
|
||||
use std::fmt::Display;
|
||||
use yew::{function_component, html, Properties, Html};
|
||||
use yew::{component, html, Properties, Html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props<T>
|
||||
@ -20,7 +20,7 @@ where
|
||||
data: T,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||
where
|
||||
T: PartialEq + Clone + Into<Html>,
|
||||
|
||||
@ -15,7 +15,7 @@ use gloo::utils::window;
|
||||
use std::mem::drop;
|
||||
|
||||
|
||||
#[function_component(ShowStorageChanged)]
|
||||
#[component(ShowStorageChanged)]
|
||||
pub fn show_storage_changed() -> Html {
|
||||
let state_storage_changed = use_state(|| false);
|
||||
|
||||
|
||||
@ -27,18 +27,18 @@ slug: /concepts/function-components
|
||||
|
||||
## 创建函数组件
|
||||
|
||||
要创建一个函数组件,请将 `#[function_component]` 属性添加到一个函数中。按照惯例,函数的名称采用 PascalCase,与 `html!` 宏中的普通 html 元素形成对比。
|
||||
要创建一个函数组件,请将 `#[component]` 属性添加到一个函数中。按照惯例,函数的名称采用 PascalCase,与 `html!` 宏中的普通 html 元素形成对比。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 然后在其他地方,您可以在 `html!` 中使用组件
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
|
||||
@ -43,26 +43,26 @@ pub struct Props {
|
||||
|
||||
## 在函数组件中使用
|
||||
|
||||
属性 `#[function_component]` 允许在函数参数中选择性地接收 Props。要提供它们,可以通过 `html!` 宏中的属性进行赋值。
|
||||
属性 `#[component]` 允许在函数参数中选择性地接收 Props。要提供它们,可以通过 `html!` 宏中的属性进行赋值。
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="with-props" label="With Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
html! { <>{"Am I loading? - "}{is_loading}</> }
|
||||
}
|
||||
|
||||
// 然后提供属性
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -73,15 +73,15 @@ fn App() -> Html {
|
||||
<TabItem value="no-props" label="No Props">
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 没有属性需要提供
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
@ -107,7 +107,7 @@ fn App() -> Html {
|
||||
使用 `Default` trait 的字段类型的默认值初始化属性值。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
@ -117,7 +117,7 @@ pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -127,12 +127,12 @@ fn HelloWorld(&Props { is_loading }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 这样使用默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
// 或者不覆盖默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <HelloWorld is_loading=true /> }
|
||||
}
|
||||
@ -158,7 +158,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -168,12 +168,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 这样使用默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// 或者不覆盖默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -202,7 +202,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -212,12 +212,12 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 使用默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case1() -> Html {
|
||||
html! { <Hello /> }
|
||||
}
|
||||
// 或者不覆盖默认值
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Case2() -> Html {
|
||||
html! { <Hello name="Sam" /> }
|
||||
}
|
||||
@ -251,7 +251,7 @@ pub struct Props {
|
||||
pub name: AttrValue,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
if is_loading {
|
||||
html! { "Loading" }
|
||||
@ -260,7 +260,7 @@ fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
// highlight-start
|
||||
let pre_made_props = yew::props! {
|
||||
@ -279,9 +279,9 @@ fn App() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_autoprops::autoprops;
|
||||
|
||||
// #[autoprops] 宏必须出现在 #[function_component] 之前,顺序很重要
|
||||
// #[autoprops] 宏必须出现在 #[component] 之前,顺序很重要
|
||||
#[autoprops]
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Greetings(
|
||||
#[prop_or_default]
|
||||
is_loading: bool,
|
||||
|
||||
@ -7,14 +7,14 @@ title: '纯组件'
|
||||
这个例子是一个纯组件。对于给定的属性 `is_loading`,它总是返回相同的 `Html`,没有任何副作用。
|
||||
|
||||
```rust
|
||||
use yew::{Properties, function_component, Html, html};
|
||||
use yew::{Properties, component, Html, html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
if props.is_loading {
|
||||
html! { "Loading" }
|
||||
|
||||
@ -100,7 +100,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent(props: &Props) -> Html {
|
||||
let Props {
|
||||
class,
|
||||
|
||||
@ -10,7 +10,7 @@ description: '使用组件层次结构创建复杂的布局'
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
html! {
|
||||
{ "This component has no properties!" }
|
||||
@ -23,7 +23,7 @@ struct Props {
|
||||
user_last_name: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponentWithProps(props: &Props) -> Html {
|
||||
let Props { user_first_name, user_last_name } = props;
|
||||
html! {
|
||||
@ -66,7 +66,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
@ -96,7 +96,7 @@ struct Props {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Container(props: &Props) -> Html {
|
||||
html! {
|
||||
<div id={props.id.clone()}>
|
||||
|
||||
@ -17,7 +17,7 @@ use web_sys::{Element, Node};
|
||||
use yew::prelude::*;
|
||||
use gloo::utils::document;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
// 带记忆能力的函数,只会执行一次
|
||||
let node = use_memo(
|
||||
|
||||
@ -100,7 +100,7 @@ use wasm_bindgen::JsCast;
|
||||
use web_sys::{EventTarget, HtmlInputElement};
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -183,7 +183,7 @@ _<sup>1</sup> 只要涉及到 JS 领域,就是安全的。_
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_value_handle = use_state(String::default);
|
||||
let input_value = (*input_value_handle).clone();
|
||||
@ -239,7 +239,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
//highlight-next-line
|
||||
let input_node_ref = use_node_ref();
|
||||
@ -285,7 +285,7 @@ fn MyComponent() -> Html {
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let input_node_ref = use_node_ref();
|
||||
|
||||
@ -338,7 +338,7 @@ use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
use web_sys::HtmlElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
@ -403,7 +403,7 @@ use yew::prelude::*;
|
||||
|
||||
use gloo::events::EventListener;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn MyComponent() -> Html {
|
||||
let div_node_ref = use_node_ref();
|
||||
|
||||
|
||||
@ -7,29 +7,28 @@ import TabItem from '@theme/TabItem'
|
||||
|
||||
## 迭代器
|
||||
|
||||
Yew 支持两种不同的语法来从迭代器构建 HTML。
|
||||
从迭代器构建 HTML 有 3 种方法:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="Syntax type 1" label="Syntax type 1">
|
||||
|
||||
第一种方法是在迭代器的最终转换上调用 `collect::<Html>()`,它返回一个 Yew 可以显示的列表。
|
||||
<TabItem value="`for` loops" label="`for` 循环">
|
||||
主要方法是使用 for 循环,与 Rust 中已有的 for 循环相同,但有 2 个关键区别:
|
||||
1. 与标准 for 循环不能返回任何内容不同,`html!` 中的 for 循环会被转换为节点列表;
|
||||
2. 发散表达式,即 `break`、`continue` 在 `html!` 中的 for 循环体内是不允许的。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
for i in 0 .. 10 {
|
||||
<span>{i}</span>
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Syntax type 2" label="Syntax type 2">
|
||||
|
||||
<TabItem value="`for` block" label="`for` 块">
|
||||
另一种方法是使用 `for` 关键字,这不是原生的 Rust 语法,而是由 HTML 宏用于输出显示迭代器所需的代码。
|
||||
当迭代器已经计算好,只需要将其传递给宏时,这种方法比第一种更好。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
@ -41,6 +40,23 @@ html! {
|
||||
{ for items.iter() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="`collect` method" label="`collect` 方法">
|
||||
|
||||
最后一种方法是在迭代器的最终转换上调用 `collect::<Html>()`,它返回一个 Yew 可以显示的列表。
|
||||
|
||||
```rust
|
||||
use yew::prelude::*;
|
||||
|
||||
let items = (1..=10).collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<ul class="item-list">
|
||||
{ items.iter().collect::<Html>() }
|
||||
</ul>
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
@ -59,7 +59,7 @@ enum Route {
|
||||
NotFound,
|
||||
}
|
||||
|
||||
#[function_component(Secure)]
|
||||
#[component(Secure)]
|
||||
fn secure() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -82,7 +82,7 @@ fn switch(routes: Route) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Main)]
|
||||
#[component(Main)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
@ -181,7 +181,7 @@ enum Route {
|
||||
以下是实现一个按钮的示例,该按钮在点击时导航到 `Home` 路由。
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(MyComponent)]
|
||||
#[component(MyComponent)]
|
||||
pub fn my_component() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
let onclick = Callback::from(move |_| navigator.push(&Route::Home));
|
||||
@ -206,7 +206,7 @@ pub fn my_component() -> Html {
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[function_component(NavItems)]
|
||||
#[component(NavItems)]
|
||||
pub fn nav_items() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
|
||||
@ -262,7 +262,7 @@ fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
`yew-router` 还在 prelude 中提供了一个 `<Redirect />` 组件。它可以用于实现与导航器 API 类似的效果。该组件接受一个 `to` 属性作为目标路由。当渲染 `<Redirect/>` 时,用户将被重定向到属性中指定的路由。以下是一个示例:
|
||||
|
||||
```rust ,ignore
|
||||
#[function_component(SomePage)]
|
||||
#[component(SomePage)]
|
||||
fn some_page() -> Html {
|
||||
// 建立对 `use_user` 的钩子
|
||||
let user = match use_user() {
|
||||
@ -435,7 +435,7 @@ fn switch_settings(route: SettingsRoute) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
pub fn app() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
|
||||
@ -18,14 +18,14 @@ description: '用于数据获取的占位标签'
|
||||
```rust ,ignore
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
@ -116,14 +116,14 @@ fn use_user() -> SuspensionResult<User> {
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(Content)]
|
||||
#[component(Content)]
|
||||
fn content() -> HtmlResult {
|
||||
let user = use_user()?;
|
||||
|
||||
Ok(html! {<div>{"Hello, "}{&user.name}</div>})
|
||||
}
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
let fallback = html! {<div>{"Loading..."}</div>};
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run, title=main.rs
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let counter = use_state(|| 0);
|
||||
let onclick = {
|
||||
|
||||
@ -26,7 +26,7 @@ description: '设置您的代码编辑器'
|
||||
pub struct $Name$Props {
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn $Name$(props: &$Name$Props) -> Html {
|
||||
html! {
|
||||
<$tag$>$END$</$tag$>
|
||||
@ -72,7 +72,7 @@ impl Component for $NAME$ {
|
||||
"#[derive(PartialEq, Properties)]",
|
||||
"pub struct ${1:ComponentName}Props {}",
|
||||
"",
|
||||
"#[function_component]",
|
||||
"#[component]",
|
||||
"pub fn $1(props: &${1}Props) -> Html {",
|
||||
" let ${1}Props {} = props;",
|
||||
" html! {",
|
||||
|
||||
@ -80,7 +80,7 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
```rust ,no_run title="src/main.rs"
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<h1>{ "Hello World" }</h1>
|
||||
@ -298,7 +298,7 @@ struct VideosListProps {
|
||||
videos: Vec<Video>,
|
||||
}
|
||||
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
videos.iter().map(|video| html! {
|
||||
<p key={video.id}>{format!("{}: {}", video.speaker, video.title)}</p>
|
||||
@ -327,7 +327,7 @@ struct Video {
|
||||
现在,我们可以更新我们的 `App` 组件以使用 `VideosList` 组件。
|
||||
|
||||
```rust ,ignore {4-7,13-14}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
- let videos = videos.iter().map(|video| html! {
|
||||
@ -365,7 +365,7 @@ struct VideosListProps {
|
||||
然后我们修改 `VideosList` 组件以将所选视频传递给回调。
|
||||
|
||||
```rust ,ignore {2-4,6-12,15-16}
|
||||
#[function_component(VideosList)]
|
||||
#[component(VideosList)]
|
||||
-fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
|
||||
+fn videos_list(VideosListProps { videos, on_click }: &VideosListProps) -> Html {
|
||||
+ let on_click = on_click.clone();
|
||||
@ -397,7 +397,7 @@ struct VideosDetailsProps {
|
||||
video: Video,
|
||||
}
|
||||
|
||||
#[function_component(VideoDetails)]
|
||||
#[component(VideoDetails)]
|
||||
fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -411,7 +411,7 @@ fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
|
||||
现在,修改 `App` 组件以在选择视频时显示 `VideoDetails` 组件。
|
||||
|
||||
```rust ,ignore {4,6-11,13-15,22-23,25-29}
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
// ...
|
||||
+ let selected_video = use_state(|| None);
|
||||
@ -500,7 +500,7 @@ struct Video {
|
||||
```rust ,ignore {1,5-25,34-35}
|
||||
+ use gloo_net::http::Request;
|
||||
|
||||
#[function_component(App)]
|
||||
#[component(App)]
|
||||
fn app() -> Html {
|
||||
- let videos = vec![
|
||||
- // ...
|
||||
|
||||
@ -108,7 +108,7 @@ pub struct ListItemProps {
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn ListItem(props: &ListItemProps) -> Html {
|
||||
let ListItemProps { value } = props.clone();
|
||||
html! {
|
||||
@ -123,7 +123,7 @@ pub struct Props {
|
||||
pub children: ChildrenWithProps<ListItem>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn List(props: &Props) -> Html {
|
||||
let modified_children = props.children.iter().map(|mut item| {
|
||||
let mut props = Rc::make_mut(&mut item.props);
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct ModalProps {
|
||||
pub children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Modal(props: &ModalProps) -> Html {
|
||||
let modal_host = gloo::utils::document()
|
||||
.get_element_by_id("modal_host")
|
||||
|
||||
@ -24,7 +24,7 @@ Yew 提供了一個 `ServerRenderer` 來在服務端渲染頁面。
|
||||
use yew::prelude::*;
|
||||
use yew::ServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -112,7 +112,7 @@ Yew 採用了不同的方法,透過 `<Suspense />` 來解決這個問題。
|
||||
use yew::prelude::*;
|
||||
use yew::Renderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {<div>{"Hello, World!"}</div>}
|
||||
}
|
||||
@ -138,7 +138,7 @@ Yew 支援以單一執行緒進行服務端渲染,透過 `yew::LocalServerRend
|
||||
use yew::prelude::*;
|
||||
use yew::LocalServerRenderer;
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
use yew_router::prelude::*;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ struct Theme {
|
||||
background: String,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -38,7 +38,7 @@ pub fn App() -> Html {
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButtonHOC() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ description: '使用上下文傳遞深度嵌套資料'
|
||||
考慮以下範例,它透過 props 傳遞主題:
|
||||
|
||||
```rust
|
||||
use yew::{html, Component, Context, Html, Properties, function_component};
|
||||
use yew::{html, Component, Context, Html, Properties, component};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Theme {
|
||||
@ -32,7 +32,7 @@ pub struct NavbarProps {
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Navbar(props: &NavbarProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -52,14 +52,14 @@ pub struct ThemeProps {
|
||||
children: Html,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn Title(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn NavButton(_props: &ThemeProps) -> Html {
|
||||
html! {
|
||||
// impl
|
||||
@ -67,7 +67,7 @@ fn NavButton(_props: &ThemeProps) -> Html {
|
||||
}
|
||||
|
||||
/// App 根節點
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let theme = Theme {
|
||||
foreground: "yellow".to_owned(),
|
||||
@ -103,7 +103,7 @@ struct Theme {
|
||||
}
|
||||
|
||||
/// 主組件
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Theme {
|
||||
foreground: "#000000".to_owned(),
|
||||
@ -122,7 +122,7 @@ pub fn App() -> Html {
|
||||
|
||||
/// 工具栏
|
||||
/// 此组件可以访问上下文。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn Toolbar() -> Html {
|
||||
html! {
|
||||
<div>
|
||||
@ -133,7 +133,7 @@ pub fn Toolbar() -> Html {
|
||||
|
||||
/// 放置在 `Toolbar` 中的按鈕
|
||||
/// 由於此元件是元件樹中 `ThemeContextProvider` 的子元件,它也可以存取上下文。
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn ThemedButton() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
|
||||
@ -22,14 +22,14 @@ let result = cb.emit(String::from("Bob")); // 呼叫回調函數
|
||||
在 yew 中的一個常見模式是建立一個回呼函數,並將其作為屬性傳遞給子元件。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub on_name_entry: Callback<String>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
|
||||
props.on_name_entry.emit(String::from("Bob"));
|
||||
@ -38,7 +38,7 @@ fn HelloWorld(props: &Props) -> Html {
|
||||
}
|
||||
|
||||
// 然後提供屬性 (Props)
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let on_name_entry: Callback<String> = Callback::from(move |name: String| {
|
||||
let greeting = format!("Hey, {}!", name);
|
||||
@ -57,9 +57,9 @@ fn App() -> Html {
|
||||
例如,這裡我們定義了一個回呼函數,當使用者點擊按鈕時將會呼叫:
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties, Callback};
|
||||
use yew::{component, html, Html, Properties, Callback};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
let onclick = Callback::from(move |_| {
|
||||
let greeting = String::from("Hi there");
|
||||
|
||||
@ -5,9 +5,9 @@ title: '子元素 (Children)'
|
||||
`Children` 是一種特殊的屬性類型,可讓您接收嵌套的 `Html`,就像 html 子元素一樣提供。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html, Properties};
|
||||
use yew::{component, html, Html, Properties};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! {
|
||||
// highlight-start
|
||||
@ -25,7 +25,7 @@ pub struct Props {
|
||||
pub children: Html, // `children` 鍵很重要!
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld(props: &Props) -> Html {
|
||||
html! {
|
||||
<div class="very-stylized-container">
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
---
|
||||
title: '泛型元件'
|
||||
description: '函數元件的 #[function_component] 屬性'
|
||||
description: '函數元件的 #[component] 屬性'
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
`#[function_component]` 屬性也適用於用於建立泛型元件的泛型函數。
|
||||
`#[component]` 屬性也適用於用於建立泛型元件的泛型函數。
|
||||
|
||||
```rust
|
||||
use std::fmt::Display;
|
||||
use yew::{function_component, html, Properties, Html};
|
||||
use yew::{component, html, Properties, Html};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props<T>
|
||||
@ -20,7 +20,7 @@ where
|
||||
data: T,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||
where
|
||||
T: PartialEq + Clone + Into<Html>,
|
||||
|
||||
@ -15,7 +15,7 @@ use gloo::utils::window;
|
||||
use std::mem::drop;
|
||||
|
||||
|
||||
#[function_component(ShowStorageChanged)]
|
||||
#[component(ShowStorageChanged)]
|
||||
pub fn show_storage_changed() -> Html {
|
||||
let state_storage_changed = use_state(|| false);
|
||||
|
||||
|
||||
@ -27,18 +27,18 @@ slug: /concepts/function-components
|
||||
|
||||
## 建立函數元件
|
||||
|
||||
若要建立函數元件,請將 `#[function_component]` 屬性加入到一個函式中。依照慣例,函數的名稱採用 PascalCase,與 `html!` 巨集中的普通 html 元素形成對比。
|
||||
若要建立函數元件,請將 `#[component]` 屬性加入到一個函式中。依照慣例,函數的名稱採用 PascalCase,與 `html!` 巨集中的普通 html 元素形成對比。
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
use yew::{component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
|
||||
// 然後在其他地方,您可以在 `html!` 中使用元件
|
||||
#[function_component]
|
||||
#[component]
|
||||
fn App() -> Html {
|
||||
html! { <HelloWorld /> }
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user