Skip to content

Commit c16fea3

Browse files
committed
fix: website lint issues - remove trailing spaces and add missing newlines
1 parent 2df159d commit c16fea3

File tree

45 files changed

+5062
-771
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+5062
-771
lines changed
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
---
2+
title: 'Children'
3+
---
4+
5+
:::caution
6+
7+
Inspecting and manipulating `Children` can often result in surprising and hard-to-explain behaviours in your application.
8+
This can lead to edge cases and often does not yield expected result.
9+
You should consider other approaches if you are trying to manipulate `Children`.
10+
11+
Yew supports using `Html` as the type of the children prop.
12+
You should use `Html` as children if you do not need `Children` or `ChildrenRenderer`.
13+
It doesn't have the drawbacks of `Children` and has a lower performance overhead.
14+
15+
:::
16+
17+
## General usage
18+
19+
_Most of the time,_ when allowing a component to have children, you don't care
20+
what type of children the component has. In such cases, the below example will
21+
suffice.
22+
23+
```rust
24+
use yew::{html, Component, Context, Html, Properties};
25+
26+
#[derive(Properties, PartialEq)]
27+
pub struct ListProps {
28+
#[prop_or_default]
29+
pub children: Html,
30+
}
31+
32+
pub struct List;
33+
34+
impl Component for List {
35+
type Message = ();
36+
type Properties = ListProps;
37+
38+
fn create(_ctx: &Context<Self>) -> Self {
39+
Self
40+
}
41+
42+
fn view(&self, ctx: &Context<Self>) -> Html {
43+
html! {
44+
<div class="list">
45+
{ctx.props().children.clone()}
46+
</div>
47+
}
48+
}
49+
}
50+
```
51+
52+
## Advanced usage
53+
54+
### Typed children
55+
56+
In cases where you want one type of component to be passed as children to your component,
57+
you can use `yew::html::ChildrenWithProps<T>`.
58+
59+
```rust
60+
use yew::{html, ChildrenWithProps, Component, Context, Html, Properties};
61+
62+
pub struct Item;
63+
64+
impl Component for Item {
65+
type Message = ();
66+
type Properties = ();
67+
68+
fn create(_ctx: &Context<Self>) -> Self {
69+
Self
70+
}
71+
72+
fn view(&self, _ctx: &Context<Self>) -> Html {
73+
html! {
74+
{ "item" }
75+
}
76+
}
77+
}
78+
79+
#[derive(Properties, PartialEq)]
80+
pub struct ListProps {
81+
#[prop_or_default]
82+
pub children: ChildrenWithProps<Item>,
83+
}
84+
85+
pub struct List;
86+
87+
impl Component for List {
88+
type Message = ();
89+
type Properties = ListProps;
90+
91+
fn create(_ctx: &Context<Self>) -> Self {
92+
Self
93+
}
94+
95+
fn view(&self, ctx: &Context<Self>) -> Html {
96+
html! {
97+
<div class="list">
98+
{ for ctx.props().children.iter() }
99+
</div>
100+
}
101+
}
102+
}
103+
```
104+
105+
## Nested Children with Props
106+
107+
Nested component properties can be accessed and mutated if the containing component types its children.
108+
109+
```rust
110+
use std::rc::Rc;
111+
use yew::prelude::*;
112+
113+
#[derive(Clone, PartialEq, Properties)]
114+
pub struct ListItemProps {
115+
value: String,
116+
}
117+
118+
#[function_component]
119+
fn ListItem(props: &ListItemProps) -> Html {
120+
let ListItemProps { value } = props.clone();
121+
html! {
122+
<span>
123+
{value}
124+
</span>
125+
}
126+
}
127+
128+
#[derive(PartialEq, Properties)]
129+
pub struct Props {
130+
pub children: ChildrenWithProps<ListItem>,
131+
}
132+
133+
#[function_component]
134+
fn List(props: &Props) -> Html {
135+
let modified_children = props.children.iter().map(|mut item| {
136+
let mut props = Rc::make_mut(&mut item.props);
137+
props.value = format!("item-{}", props.value);
138+
item
139+
});
140+
html! { for modified_children }
141+
}
142+
143+
html! {
144+
<List>
145+
<ListItem value="a" />
146+
<ListItem value="b" />
147+
<ListItem value="c" />
148+
</List>
149+
};
150+
```
151+
152+
### Enum typed children
153+
154+
Of course, sometimes you might need to restrict the children to a few different
155+
components. In these cases, you have to get a little more hands-on with Yew.
156+
157+
The [`derive_more`](https://github.com/JelteF/derive_more) crate is used here
158+
for better ergonomics. If you don't want to use it, you can manually implement
159+
`From` for each variant.
160+
161+
```rust
162+
use yew::{
163+
html, html::ChildrenRenderer, virtual_dom::VChild, Component,
164+
Context, Html, Properties,
165+
};
166+
167+
pub struct Primary;
168+
169+
impl Component for Primary {
170+
type Message = ();
171+
type Properties = ();
172+
173+
fn create(_ctx: &Context<Self>) -> Self {
174+
Self
175+
}
176+
177+
fn view(&self, _ctx: &Context<Self>) -> Html {
178+
html! {
179+
{ "Primary" }
180+
}
181+
}
182+
}
183+
184+
pub struct Secondary;
185+
186+
impl Component for Secondary {
187+
type Message = ();
188+
type Properties = ();
189+
190+
fn create(_ctx: &Context<Self>) -> Self {
191+
Self
192+
}
193+
194+
fn view(&self, _ctx: &Context<Self>) -> Html {
195+
html! {
196+
{ "Secondary" }
197+
}
198+
}
199+
}
200+
201+
#[derive(Clone, derive_more::From, PartialEq)]
202+
pub enum Item {
203+
Primary(VChild<Primary>),
204+
Secondary(VChild<Secondary>),
205+
}
206+
207+
// Now, we implement `Into<Html>` so that yew knows how to render `Item`.
208+
#[allow(clippy::from_over_into)]
209+
impl Into<Html> for Item {
210+
fn into(self) -> Html {
211+
match self {
212+
Self::Primary(child) => child.into(),
213+
Self::Secondary(child) => child.into(),
214+
}
215+
}
216+
}
217+
218+
#[derive(Properties, PartialEq)]
219+
pub struct ListProps {
220+
#[prop_or_default]
221+
pub children: ChildrenRenderer<Item>,
222+
}
223+
224+
pub struct List;
225+
226+
impl Component for List {
227+
type Message = ();
228+
type Properties = ListProps;
229+
230+
fn create(_ctx: &Context<Self>) -> Self {
231+
Self
232+
}
233+
234+
fn view(&self, ctx: &Context<Self>) -> Html {
235+
html! {
236+
<div class="list">
237+
{ for ctx.props().children.iter() }
238+
</div>
239+
}
240+
}
241+
}
242+
```
243+
244+
### Optional typed child
245+
246+
You can also have a single optional child component of a specific type too:
247+
248+
```rust
249+
use yew::{
250+
html, html_nested, virtual_dom::VChild, Component,
251+
Context, Html, Properties
252+
};
253+
254+
pub struct PageSideBar;
255+
256+
impl Component for PageSideBar {
257+
type Message = ();
258+
type Properties = ();
259+
260+
fn create(_ctx: &Context<Self>) -> Self {
261+
Self
262+
}
263+
264+
fn view(&self, _ctx: &Context<Self>) -> Html {
265+
html! {
266+
{ "sidebar" }
267+
}
268+
}
269+
}
270+
271+
#[derive(Properties, PartialEq)]
272+
pub struct PageProps {
273+
#[prop_or_default]
274+
pub sidebar: Option<VChild<PageSideBar>>,
275+
}
276+
277+
struct Page;
278+
279+
impl Component for Page {
280+
type Message = ();
281+
type Properties = PageProps;
282+
283+
fn create(_ctx: &Context<Self>) -> Self {
284+
Self
285+
}
286+
287+
fn view(&self, ctx: &Context<Self>) -> Html {
288+
html! {
289+
<div class="page">
290+
{ ctx.props().sidebar.clone().map(Html::from).unwrap_or_default() }
291+
// ... page content
292+
</div>
293+
}
294+
}
295+
}
296+
297+
// The page component can be called either with the sidebar or without:
298+
299+
pub fn render_page(with_sidebar: bool) -> Html {
300+
if with_sidebar {
301+
// Page with sidebar
302+
html! {
303+
<Page sidebar={html_nested! {
304+
<PageSideBar />
305+
}} />
306+
}
307+
} else {
308+
// Page without sidebar
309+
html! {
310+
<Page />
311+
}
312+
}
313+
}
314+
```
315+
316+
## Further Reading
317+
318+
- For a real-world example of this pattern, check out the yew-router source code. For a more advanced example, check out the [nested-list example](https://github.com/yewstack/yew/tree/master/examples/nested_list) in the main yew repository.
Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,74 @@
11
---
2-
title: How it works
3-
description: Low level details about the framework
2+
title: 'How it works'
3+
description: 'Low level details about the framework'
44
---
55

6-
# 低レベルなライブラリの中身
6+
# Low-level library internals
77

8-
コンポーネントのライフサイクルの状態機械、VDOM の異なるアルゴリズム
8+
## Under the hood of the `html!` macro
9+
10+
The `html!` macro turns code written in a custom HTML-like syntax into valid Rust code. Using this
11+
macro is not necessary for developing Yew applications, but it is recommended. The code generated
12+
by this macro makes use of the public Yew library API which can be used directly if you wish. Note
13+
that some methods used are undocumented intentionally to avoid accidental misuse. With each
14+
update of `yew-macro`, the generated code will be more efficient and handle any breaking changes
15+
without many (if any) modifications to the `html!` syntax.
16+
17+
Because the `html!` macro allows you to write code in a declarative style, your UI layout code will
18+
closely match the HTML that is generated for the page. This becomes increasingly useful as your
19+
application gets more interactive and your codebase gets larger. Rather than manually writing
20+
all of the code to manipulate the DOM yourself, the macro will handle it for you.
21+
22+
Using the `html!` macro can feel pretty magical, but it has nothing to hide. If you are curious about
23+
how it works, try expanding the `html!` macro calls in your program. There is a useful command called
24+
`cargo expand` which allows you to see the expansion of Rust macros. `cargo expand` does not ship with
25+
`cargo` by default so you will need to install it with `cargo install cargo-expand` if you have not
26+
already. [Rust-Analyzer](https://rust-analyzer.github.io/) also provides a mechanism for
27+
[obtaining macro output from within an IDE](https://rust-analyzer.github.io/manual.html#expand-macro-recursively).
28+
29+
Output from the `html!` macro is often pretty terse! This is a feature: machine-generated code can
30+
sometimes clash with other code in an application. To prevent issues, `proc_macro`
31+
"hygiene" is adhered to. Some examples include:
32+
33+
1. Instead of using `yew::<module>` the macro generates `::yew::<module>` to make sure that the
34+
Yew package is referenced correctly. This is also why `::alloc::vec::Vec::new()` is called instead
35+
of just `Vec::new()`.
36+
2. Due to potential trait method name collisions, `<Type as Trait>` is used to make sure that we are
37+
using members from the correct trait.
38+
39+
## What is a virtual DOM?
40+
41+
The DOM ("document object model") is a representation of the HTML content that is managed by the browser
42+
for your web page. A "virtual" DOM is simply a copy of the DOM that is held in application memory. Managing
43+
a virtual DOM results in a higher memory overhead, but allows for batching and faster reads by avoiding
44+
or delaying the use of browser APIs.
45+
46+
Having a copy of the DOM in memory can be helpful for libraries that promote the use of
47+
declarative UIs. Rather than needing specific code for describing how the DOM should be modified
48+
in response to a user event, the library can use a generalized approach with DOM "diffing". When a Yew
49+
component is updated and wants to change how it is rendered, the Yew library will build a second copy
50+
of the virtual DOM and directly compare it to a virtual DOM which mirrors what is currently on screen.
51+
The "diff" (or difference) between the two can be broken down into incremental updates and applied in
52+
a batch with browser APIs. Once the updates are applied, the old virtual DOM copy is discarded and the
53+
new copy is saved for future diff checks.
54+
55+
This "diff" algorithm can be optimized over time to improve the performance of complex applications.
56+
Since Yew applications are run with WebAssembly, we believe that Yew has a competitive edge to adopt
57+
more sophisticated algorithms in the future.
58+
59+
The Yew virtual DOM is not exactly one-to-one with the browser DOM. It also includes "lists" and
60+
"components" for organizing DOM elements. A list can simply be an ordered list of elements but can
61+
also be much more powerful. By annotating each list element with a "key", application developers
62+
can help Yew make additional optimizations to ensure that when a list changes, the least amount
63+
of work is done to calculate the diff update. Similarly, components provide custom logic to
64+
indicate whether a re-render is required to help with performance.
65+
66+
## Yew scheduler and component-scoped event loop
67+
68+
_Contribute to the docs – explain how `yew::scheduler` and `yew::html::scope` work in depth_
69+
70+
## Further reading
71+
72+
- [More information about macros from the Rust Book](https://doc.rust-lang.org/stable/book/ch19-06-macros.html)
73+
- [More information about `cargo-expand`](https://github.com/dtolnay/cargo-expand)
74+
- [The API documentation for `yew::virtual_dom`](https://docs.rs/yew/*/yew/virtual_dom/index.html)

0 commit comments

Comments
 (0)