mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
GitBook: [master] 29 pages modified
This commit is contained in:
parent
5c3a71713c
commit
6042da816a
@ -6,13 +6,9 @@ description: Make your app faster
|
||||
|
||||
## neq\_assign
|
||||
|
||||
When a component receives props from its parent component, the `change` method is called. This, in
|
||||
addition to allowing you to update the component's state, also allows you to return a `ShouldRender`
|
||||
boolean value that indicates if the component should re-render itself in response to the prop changes.
|
||||
When a component receives props from its parent component, the `change` method is called. This, in addition to allowing you to update the component's state, also allows you to return a `ShouldRender` boolean value that indicates if the component should re-render itself in response to the prop changes.
|
||||
|
||||
Re-rendering is expensive, and if you can avoid it, you should. As a general rule, you only want to
|
||||
re-render when the props actually changed. The following block of code represents this rule,
|
||||
returning `true` if the props differed from the previous props:
|
||||
Re-rendering is expensive, and if you can avoid it, you should. As a general rule, you only want to re-render when the props actually changed. The following block of code represents this rule, returning `true` if the props differed from the previous props:
|
||||
|
||||
```rust
|
||||
use yew::ShouldRender;
|
||||
@ -36,68 +32,37 @@ impl Example {
|
||||
}
|
||||
```
|
||||
|
||||
But we can go further! This is six lines of boilerplate can be reduced down to one by using a trait
|
||||
and a blanket implementation for anything that implements `PartialEq`. Check out the `yewtil` crate's
|
||||
`NeqAssign` trait [here](https://docs.rs/yewtil/*/yewtil/trait.NeqAssign.html).
|
||||
But we can go further! This is six lines of boilerplate can be reduced down to one by using a trait and a blanket implementation for anything that implements `PartialEq`. Check out the `yewtil` crate's `NeqAssign` trait [here](https://docs.rs/yewtil/*/yewtil/trait.NeqAssign.html).
|
||||
|
||||
## RC
|
||||
|
||||
In an effort to avoid cloning large chunks of data to create props when re-rendering, we can use
|
||||
smart pointers to only clone the pointer instead. If you use `Rc<_>`s in your props and child
|
||||
components instead of plain unboxed values, you can delay cloning until you need to modify the data
|
||||
in the child component, where you use `Rc::make_mut` to clone and get a mutable reference to the data
|
||||
you want to alter. By not cloning until mutation, child components can reject props identical to
|
||||
their state-owned props in `Component::change` for almost no performance cost, versus the case where
|
||||
the data itself needs to be copied into the props struct in the parent before it is compared and
|
||||
rejected in the child.
|
||||
In an effort to avoid cloning large chunks of data to create props when re-rendering, we can use smart pointers to only clone the pointer instead. If you use `Rc<_>`s in your props and child components instead of plain unboxed values, you can delay cloning until you need to modify the data in the child component, where you use `Rc::make_mut` to clone and get a mutable reference to the data you want to alter. By not cloning until mutation, child components can reject props identical to their state-owned props in `Component::change` for almost no performance cost, versus the case where the data itself needs to be copied into the props struct in the parent before it is compared and rejected in the child.
|
||||
|
||||
This optimization is most useful for data types that aren't `Copy`. If you can copy your data easily,
|
||||
then it probably isn't worth putting it behind a smart pointer. For structures that can contain lots
|
||||
of data like `Vec`, `HashMap`, and `String`, this optimization should be worthwhile.
|
||||
This optimization is most useful for data types that aren't `Copy`. If you can copy your data easily, then it probably isn't worth putting it behind a smart pointer. For structures that can contain lots of data like `Vec`, `HashMap`, and `String`, this optimization should be worthwhile.
|
||||
|
||||
This optimization works best if the values are never updated by the children, and even better, if
|
||||
they are rarely updated by parents. This makes `Rc<_>s` a good choice for wrapping property values in
|
||||
for pure components.
|
||||
This optimization works best if the values are never updated by the children, and even better, if they are rarely updated by parents. This makes `Rc<_>s` a good choice for wrapping property values in for pure components.
|
||||
|
||||
## View Functions
|
||||
|
||||
For code readability reasons, it often makes sense to migrate sections of `html!` to their own
|
||||
functions so you can avoid the rightward drift present in deeply nested HTML.
|
||||
For code readability reasons, it often makes sense to migrate sections of `html!` to their own functions so you can avoid the rightward drift present in deeply nested HTML.
|
||||
|
||||
## Pure Components/Function Components
|
||||
|
||||
Pure components are components that don't mutate their state, only displaying content and propagating
|
||||
messages up to normal, mutable components. They differ from view functions in that they can be used
|
||||
from within the `html!` macro using the component syntax \(`<SomePureComponent />`\) instead of
|
||||
expression syntax \(`{some_view_function()}`\), and that depending on their implementation, they can
|
||||
be memoized - preventing re-renders for identical props using the aforementioned `neq_assign` logic.
|
||||
Pure components are components that don't mutate their state, only displaying content and propagating messages up to normal, mutable components. They differ from view functions in that they can be used from within the `html!` macro using the component syntax \(`<SomePureComponent />`\) instead of expression syntax \(`{some_view_function()}`\), and that depending on their implementation, they can be memoized - preventing re-renders for identical props using the aforementioned `neq_assign` logic.
|
||||
|
||||
Yew doesn't natively support pure or function components, but they are available via external crates.
|
||||
|
||||
Function components don't exist yet, but in theory, pure components could be generated by using proc
|
||||
macros and annotating functions.
|
||||
Function components don't exist yet, but in theory, pure components could be generated by using proc macros and annotating functions.
|
||||
|
||||
## Keyed DOM nodes when they arrive
|
||||
|
||||
## Compile speed optimizations using Cargo Workspaces
|
||||
|
||||
Arguably, the largest drawback to using Yew is the long time it takes to compile. Compile time seems
|
||||
to correlate with the quantity of code found within `html!` macro blocks. This tends to not be a
|
||||
significant problem for smaller projects, but for web apps that span multiple pages, it makes sense
|
||||
to break apart your code across multiple crates to minimize the amount of work the compiler has to do
|
||||
for each change made.
|
||||
Arguably, the largest drawback to using Yew is the long time it takes to compile. Compile time seems to correlate with the quantity of code found within `html!` macro blocks. This tends to not be a significant problem for smaller projects, but for web apps that span multiple pages, it makes sense to break apart your code across multiple crates to minimize the amount of work the compiler has to do for each change made.
|
||||
|
||||
You should try to make your main crate handle routing/page selection, move all commonly shared code
|
||||
to another crate, and then make a different crate for each page, where each page could be a different
|
||||
component, or just a big function that produces `Html`. In the best case scenario, you go from
|
||||
rebuilding all of your code on each compile to rebuilding only the main crate, and one of your page
|
||||
crates. In the worst case, where you edit something in the "common" crate, you will be right back to
|
||||
where you started: compiling all code that depends on that commonly shared crate, which is
|
||||
probably everything else.
|
||||
You should try to make your main crate handle routing/page selection, move all commonly shared code to another crate, and then make a different crate for each page, where each page could be a different component, or just a big function that produces `Html`. In the best case scenario, you go from rebuilding all of your code on each compile to rebuilding only the main crate, and one of your page crates. In the worst case, where you edit something in the "common" crate, you will be right back to where you started: compiling all code that depends on that commonly shared crate, which is probably everything else.
|
||||
|
||||
If your main crate is too heavyweight, or you want to rapidly iterate on a deeply nested page \(eg. a
|
||||
page that renders on top of another page\), you can use an example crate to create a more simple
|
||||
implementation of the main page and render your work-in-progress component on top of that.
|
||||
If your main crate is too heavyweight, or you want to rapidly iterate on a deeply nested page \(eg. a page that renders on top of another page\), you can use an example crate to create a more simple implementation of the main page and render your work-in-progress component on top of that.
|
||||
|
||||
## Build size optimization
|
||||
|
||||
@ -106,19 +71,13 @@ implementation of the main page and render your work-in-progress component on to
|
||||
* `cargo.toml` \( defining release profile \)
|
||||
* optimize wasm code using `wasm-opt`
|
||||
|
||||
More information about code size profiling:
|
||||
[rustwasm book](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size)
|
||||
More information about code size profiling: [rustwasm book](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size)
|
||||
|
||||
### wee\_alloc
|
||||
|
||||
[wee\_alloc](https://github.com/rustwasm/wee_alloc) is a tiny allocator that is much smaller than the
|
||||
allocator that is normally used in Rust binaries. Replacing the default allocator with this one will
|
||||
result in smaller WASM file sizes, at the expense of speed and memory overhead.
|
||||
[wee\_alloc](https://github.com/rustwasm/wee_alloc) is a tiny allocator that is much smaller than the allocator that is normally used in Rust binaries. Replacing the default allocator with this one will result in smaller WASM file sizes, at the expense of speed and memory overhead.
|
||||
|
||||
The slower speed and memory overhead are minor in comparison to the size gains made by not including
|
||||
the default allocator. This smaller file size means that your page will load faster, and so it is
|
||||
generally recommended that you use this allocator over the default, unless your app is doing some
|
||||
allocation-heavy work.
|
||||
The slower speed and memory overhead are minor in comparison to the size gains made by not including the default allocator. This smaller file size means that your page will load faster, and so it is generally recommended that you use this allocator over the default, unless your app is doing some allocation-heavy work.
|
||||
|
||||
```rust
|
||||
// Use `wee_alloc` as the global allocator.
|
||||
@ -152,8 +111,7 @@ Further more it is possible to optimize size of `wasm` code.
|
||||
|
||||
wasm-opt info: [binaryen project](https://github.com/WebAssembly/binaryen)
|
||||
|
||||
The Rust Wasm book features a section about reducing the size of WASM binaries:
|
||||
[Shrinking .wasm size](https://rustwasm.github.io/book/game-of-life/code-size.html)
|
||||
The Rust Wasm book features a section about reducing the size of WASM binaries: [Shrinking .wasm size](https://rustwasm.github.io/book/game-of-life/code-size.html)
|
||||
|
||||
* using `wasm-pack` which by default optimizes `wasm` code in release builds
|
||||
* using `wasm-opt` directly on `wasm` files.
|
||||
@ -164,8 +122,7 @@ wasm-opt wasm_bg.wasm -Os -o wasm_bg_opt.wasm
|
||||
|
||||
#### Build size of 'minimal' example in yew/examples/
|
||||
|
||||
Note: `wasm-pack` combines optimization for Rust and Wasm code. `wasm-bindgen` is used in this
|
||||
example without any Rust size optimization.
|
||||
Note: `wasm-pack` combines optimization for Rust and Wasm code. `wasm-bindgen` is used in this example without any Rust size optimization.
|
||||
|
||||
| used tool | size |
|
||||
| :--- | :--- |
|
||||
|
||||
@ -4,16 +4,9 @@ description: Yew's Actor System
|
||||
|
||||
# Agents
|
||||
|
||||
Agents are similar to Angular's [Services](https://angular.io/guide/architecture-services) \(but
|
||||
without dependency injection\), and provide a Yew with an
|
||||
[Actor Model](https://en.wikipedia.org/wiki/Actor_model). Agents can be used to route messages
|
||||
between components independently of where they sit in the component hierarchy, or they can be used to
|
||||
create a shared state, and they can also be used to offload computationally expensive tasks from the
|
||||
main thread which renders the UI. There is also planned support for using agents to allow Yew
|
||||
applications to communicate across tabs \(in the future\).
|
||||
Agents are similar to Angular's [Services](https://angular.io/guide/architecture-services) \(but without dependency injection\), and provide a Yew with an [Actor Model](https://en.wikipedia.org/wiki/Actor_model). Agents can be used to route messages between components independently of where they sit in the component hierarchy, or they can be used to create a shared state, and they can also be used to offload computationally expensive tasks from the main thread which renders the UI. There is also planned support for using agents to allow Yew applications to communicate across tabs \(in the future\).
|
||||
|
||||
In order for agents to run concurrently, Yew uses
|
||||
[web-workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
|
||||
In order for agents to run concurrently, Yew uses [web-workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
|
||||
|
||||
## Lifecycle
|
||||
|
||||
@ -24,12 +17,19 @@ In order for agents to run concurrently, Yew uses
|
||||
#### Reaches
|
||||
|
||||
* Context - There will exist at most one instance of a Context Agent at any given time. Bridges will
|
||||
spawn or connect to an already spawned agent on the UI thread. This can be used to coordinate state
|
||||
between components or other agents. When no bridges are connected to this agent, the agent will
|
||||
disappear.
|
||||
|
||||
spawn or connect to an already spawned agent on the UI thread. This can be used to coordinate state
|
||||
|
||||
between components or other agents. When no bridges are connected to this agent, the agent will
|
||||
|
||||
disappear.
|
||||
|
||||
* Job - Spawn a new agent on the UI thread for every new bridge. This is good for moving shared but
|
||||
independent behavior that communicates with the browser out of components. \(TODO verify\) When the
|
||||
task is done, the agent will disappear.
|
||||
|
||||
independent behavior that communicates with the browser out of components. \(TODO verify\) When the
|
||||
|
||||
task is done, the agent will disappear.
|
||||
|
||||
* Public - Same as Context, but runs on its own web worker.
|
||||
* Private - Same as Job, but runs on its own web worker.
|
||||
* Global \(WIP\)
|
||||
@ -38,24 +38,19 @@ task is done, the agent will disappear.
|
||||
|
||||
### Bridges
|
||||
|
||||
A bridge allows bi-directional communication between an agent and a component. Bridges also allow
|
||||
agents to communicate with one another.
|
||||
A bridge allows bi-directional communication between an agent and a component. Bridges also allow agents to communicate with one another.
|
||||
|
||||
### Dispatchers
|
||||
|
||||
A dispatcher allows uni-directional communication between a component and an agent. A dispatcher
|
||||
allows a component to send messages to an agent.
|
||||
A dispatcher allows uni-directional communication between a component and an agent. A dispatcher allows a component to send messages to an agent.
|
||||
|
||||
## Overhead
|
||||
|
||||
Agents that live in their own separate web worker (Private and Public) incur serialization overhead
|
||||
on the messages they send and receive. They use [bincode](https://github.com/servo/bincode) to
|
||||
communicate with other threads, so the cost is substantially higher than just calling a function.
|
||||
Unless the cost of computation will outweigh the cost of message passing, you should contain your
|
||||
logic in the UI thread agents (Job or Context).
|
||||
Agents that live in their own separate web worker \(Private and Public\) incur serialization overhead on the messages they send and receive. They use [bincode](https://github.com/servo/bincode) to communicate with other threads, so the cost is substantially higher than just calling a function. Unless the cost of computation will outweigh the cost of message passing, you should contain your logic in the UI thread agents \(Job or Context\).
|
||||
|
||||
## Further reading
|
||||
|
||||
* The [pub\_sub](https://github.com/yewstack/yew/tree/master/examples/pub_sub) example shows how
|
||||
components can use agents to communicate with each other.
|
||||
|
||||
components can use agents to communicate with each other.
|
||||
|
||||
|
||||
@ -6,9 +6,7 @@ description: Components and their lifecycle hooks
|
||||
|
||||
## What are Components?
|
||||
|
||||
Components are the building blocks of Yew. They manage their own state and can render themselves to
|
||||
the DOM. Components are created by implementing the `Component` trait which describes the lifecycle
|
||||
of a component.
|
||||
Components are the building blocks of Yew. They manage their own state and can render themselves to the DOM. Components are created by implementing the `Component` trait which describes the lifecycle of a component.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
@ -20,9 +18,7 @@ of a component.
|
||||
|
||||
### Create
|
||||
|
||||
When a component is created, it receives properties from its parent component as well as a
|
||||
`ComponentLink`. The properties can be used to initialize the component's state and the "link" can be
|
||||
used to register callbacks or send messages to the component.
|
||||
When a component is created, it receives properties from its parent component as well as a `ComponentLink`. The properties can be used to initialize the component's state and the "link" can be used to register callbacks or send messages to the component.
|
||||
|
||||
It is common to store the props and the link in your component struct, like so:
|
||||
|
||||
@ -46,9 +42,7 @@ impl Component for MyComponent {
|
||||
|
||||
### View
|
||||
|
||||
Components declare their layout in the `view()` method. Yew provides the `html!` macro for declaring
|
||||
HTML and SVG nodes and their listeners as well as child components. The macro acts a lot like React's
|
||||
JSX, but uses Rust expressions instead of JavaScript.
|
||||
Components declare their layout in the `view()` method. Yew provides the `html!` macro for declaring HTML and SVG nodes and their listeners as well as child components. The macro acts a lot like React's JSX, but uses Rust expressions instead of JavaScript.
|
||||
|
||||
```rust
|
||||
impl Component for MyComponent {
|
||||
@ -69,10 +63,7 @@ For usage details, check out the `html!` guide:
|
||||
|
||||
### Rendered
|
||||
|
||||
The `rendered()` component lifecycle method is called after `view()` is processed and Yew has
|
||||
rendered your component, but before the browser refreshes the page. A component may wish to implement
|
||||
this method to perform actions that can only be done after the component has rendered elements. You
|
||||
can check whether this is the first time the component was rendered via the `first_render` parameter.
|
||||
The `rendered()` component lifecycle method is called after `view()` is processed and Yew has rendered your component, but before the browser refreshes the page. A component may wish to implement this method to perform actions that can only be done after the component has rendered elements. You can check whether this is the first time the component was rendered via the `first_render` parameter.
|
||||
|
||||
```rust
|
||||
use stdweb::web::html_element::InputElement;
|
||||
@ -108,10 +99,7 @@ Note that this lifecycle method does not require an implementation and will do n
|
||||
|
||||
### Update
|
||||
|
||||
Components are dynamic and can register to receive asynchronous messages. The `update()` lifecycle
|
||||
method is called for each message. This allows the component to update itself based on what the
|
||||
message was, and determine if it needs to re-render itself. Messages can be triggered by HTML elements
|
||||
listeners or be sent by child components, Agents, Services, or Futures.
|
||||
Components are dynamic and can register to receive asynchronous messages. The `update()` lifecycle method is called for each message. This allows the component to update itself based on what the message was, and determine if it needs to re-render itself. Messages can be triggered by HTML elements listeners or be sent by child components, Agents, Services, or Futures.
|
||||
|
||||
Here's an example of what `update()` could look like:
|
||||
|
||||
@ -142,9 +130,7 @@ impl Component for MyComponent {
|
||||
|
||||
### Change
|
||||
|
||||
Components may be re-rendered by their parents. When this happens, they could receive new properties
|
||||
and choose to re-render. This design facilitates parent to child component communication through
|
||||
changed properties.
|
||||
Components may be re-rendered by their parents. When this happens, they could receive new properties and choose to re-render. This design facilitates parent to child component communication through changed properties.
|
||||
|
||||
A typical implementation would look like:
|
||||
|
||||
@ -165,8 +151,7 @@ impl Component for MyComponent {
|
||||
|
||||
### Destroy
|
||||
|
||||
After Components are unmounted from the DOM, Yew calls the `destroy()` lifecycle method to support
|
||||
any necessary clean up operations. This method is optional and does nothing by default.
|
||||
After Components are unmounted from the DOM, Yew calls the `destroy()` lifecycle method to support any necessary clean up operations. This method is optional and does nothing by default.
|
||||
|
||||
## Associated Types
|
||||
|
||||
@ -181,10 +166,7 @@ impl Component for MyComponent {
|
||||
}
|
||||
```
|
||||
|
||||
`Message` represents a variety of messages that can be processed by the component to trigger some
|
||||
side effect. For example, you may have a `Click` message which triggers an API request or toggles the
|
||||
appearance of a UI component. It is common practice to create an enum called `Msg` in your component's
|
||||
module and use that as the message type in the component. It is common to shorten "message" to "msg".
|
||||
`Message` represents a variety of messages that can be processed by the component to trigger some side effect. For example, you may have a `Click` message which triggers an API request or toggles the appearance of a UI component. It is common practice to create an enum called `Msg` in your component's module and use that as the message type in the component. It is common to shorten "message" to "msg".
|
||||
|
||||
```rust
|
||||
enum Msg {
|
||||
@ -192,12 +174,5 @@ enum Msg {
|
||||
}
|
||||
```
|
||||
|
||||
`Properties` represents the information passed to a component from its parent. This type must
|
||||
implements the `Properties` trait \(usually by deriving it\) and can specify whether certain
|
||||
properties are required or optional. This type is used when creating and updating a component. It is
|
||||
common practice to create a struct called `Props` in your component's module and use that as the
|
||||
component's `Properties` type. It is common to shorten "properties" to "props". Since props are handed
|
||||
down from parent components, the root component of your application typically has a `Properties` type
|
||||
of `()`. If you wish to specify properties for your root component, use the `App::mount_with_props`
|
||||
method.
|
||||
`Properties` represents the information passed to a component from its parent. This type must implements the `Properties` trait \(usually by deriving it\) and can specify whether certain properties are required or optional. This type is used when creating and updating a component. It is common practice to create a struct called `Props` in your component's module and use that as the component's `Properties` type. It is common to shorten "properties" to "props". Since props are handed down from parent components, the root component of your application typically has a `Properties` type of `()`. If you wish to specify properties for your root component, use the `App::mount_with_props` method.
|
||||
|
||||
|
||||
@ -4,37 +4,27 @@ description: ComponentLink and Callbacks
|
||||
|
||||
# Callbacks
|
||||
|
||||
The component "link" is the mechanism through which components are able to register callbacks and
|
||||
update themselves.
|
||||
The component "link" is the mechanism through which components are able to register callbacks and update themselves.
|
||||
|
||||
## ComponentLink API
|
||||
|
||||
### callback
|
||||
|
||||
Registers a callback that will send a message to the component's update mechanism when it is executed.
|
||||
Under the hood, it will call `send_self` with the message that is returned by the provided closure.
|
||||
A `Fn(IN) -> Vec<COMP::Message>` is provided and a `Callback<IN>` is returned.
|
||||
Registers a callback that will send a message to the component's update mechanism when it is executed. Under the hood, it will call `send_self` with the message that is returned by the provided closure. A `Fn(IN) -> Vec<COMP::Message>` is provided and a `Callback<IN>` is returned.
|
||||
|
||||
### send\_message
|
||||
|
||||
Sends a message to the component immediately after the current loop finishes, causing another update
|
||||
loop to initiate.
|
||||
Sends a message to the component immediately after the current loop finishes, causing another update loop to initiate.
|
||||
|
||||
### send\_message\_batch
|
||||
|
||||
Registers a callback that sends a batch of many messages at once when it is executed. If any of the
|
||||
messages cause the component to re-render, the component will re-render after all messages in the
|
||||
batch have been processed. A `Fn(IN) -> COMP::Message` is provided and a `Callback<IN>` is returned.
|
||||
Registers a callback that sends a batch of many messages at once when it is executed. If any of the messages cause the component to re-render, the component will re-render after all messages in the batch have been processed. A `Fn(IN) -> COMP::Message` is provided and a `Callback<IN>` is returned.
|
||||
|
||||
## Callbacks
|
||||
|
||||
_\(This might need its own short page.\)_
|
||||
|
||||
Callbacks are used to communicate with services, agents, and parent components within Yew. They are
|
||||
just a `Fn` wrapped by an `Rc` to allow them to be cloned.
|
||||
Callbacks are used to communicate with services, agents, and parent components within Yew. They are just a `Fn` wrapped by an `Rc` to allow them to be cloned.
|
||||
|
||||
They have an `emit` function that takes their `<IN>` type as an argument and converts that to a message expected by its destination. If a callback from a parent is provided in props to a child component, the child can call `emit` on the callback in its `update` lifecycle hook to send a message back to its parent. Closures or Functions provided as props inside the `html!` macro are automatically converted to Callbacks.
|
||||
|
||||
They have an `emit` function that takes their `<IN>` type as an argument and converts that to a
|
||||
message expected by its destination. If a callback from a parent is provided in props to a child
|
||||
component, the child can call `emit` on the callback in its `update` lifecycle hook to send a message
|
||||
back to its parent. Closures or Functions provided as props inside the `html!` macro are
|
||||
automatically converted to Callbacks.
|
||||
|
||||
@ -11,45 +11,26 @@ Properties enable child and parent components to communicate with each other.
|
||||
Don't try to implement `Properties` yourself, derive it by using `#[derive(Properties)]` instead.
|
||||
|
||||
{% hint style="info" %}
|
||||
Types for which you derive `Properties` must also implement `Clone`. This can be done by either using
|
||||
`#[derive(Properties, Clone)` or manually implementing `Clone` for your type.
|
||||
Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)` or manually implementing `Clone` for your type.
|
||||
{% endhint %}
|
||||
|
||||
### Required attributes
|
||||
|
||||
The fields within a struct that derives `Properties` are required by default. When a field is missing
|
||||
and the component is created in the `html!` macro, a compiler error is returned. For fields with
|
||||
optional properties, use the `#[prop_or_default]` attribute to use the default value for that type
|
||||
when the prop is not specified. To specify a value, use the `#[prop_or(value)]` attribute where value
|
||||
is the default value for the property or alternatively use `#[prop_or_else(function)]` where
|
||||
`function` returns the default value. For example, to default a boolean value as `true`, use the
|
||||
attribute `#[prop_or(true)]`. It is common for optional properties to use the `Option` enum which has the default value `None`.
|
||||
The fields within a struct that derives `Properties` are required by default. When a field is missing and the component is created in the `html!` macro, a compiler error is returned. For fields with optional properties, use the `#[prop_or_default]` attribute to use the default value for that type when the prop is not specified. To specify a value, use the `#[prop_or(value)]` attribute where value is the default value for the property or alternatively use `#[prop_or_else(function)]` where `function` returns the default value. For example, to default a boolean value as `true`, use the attribute `#[prop_or(true)]`. It is common for optional properties to use the `Option` enum which has the default value `None`.
|
||||
|
||||
### PartialEq
|
||||
|
||||
It is likely to make sense to derive `PartialEq` on your props if you can do this. Using `PartialEq`
|
||||
makes it much easier to avoid unnecessary rerendering \(this is explained in the
|
||||
**Optimizations & Best Practices** section\).
|
||||
It is likely to make sense to derive `PartialEq` on your props if you can do this. Using `PartialEq` makes it much easier to avoid unnecessary rerendering \(this is explained in the **Optimizations & Best Practices** section\).
|
||||
|
||||
## Memory/speed overhead of using Properties
|
||||
|
||||
In `Component::view`, you take a reference to the component's state, and use that to create `Html`.
|
||||
Properties, however, are owned values. This means that in order to create them and pass them to child
|
||||
components, we need to take ownership of the references provided in the `view` function. This is
|
||||
done by implicitly cloning the references as they are passed to components in order to get owned
|
||||
values.
|
||||
In `Component::view`, you take a reference to the component's state, and use that to create `Html`. Properties, however, are owned values. This means that in order to create them and pass them to child components, we need to take ownership of the references provided in the `view` function. This is done by implicitly cloning the references as they are passed to components in order to get owned values.
|
||||
|
||||
This means that each component has its own distinct copy of the state passed down from its parent,
|
||||
and that whenever you re-render a component, the props for all child components of the re-rendering
|
||||
component will have to be cloned.
|
||||
This means that each component has its own distinct copy of the state passed down from its parent, and that whenever you re-render a component, the props for all child components of the re-rendering component will have to be cloned.
|
||||
|
||||
The implication of this is if you would otherwise be passing _huge_ amounts of data down as props
|
||||
\(Strings that are 10s of kilobytes in size\), you may want to consider turning your child component
|
||||
into a function which returns `Html` that the parent calls, as this means that data does not have
|
||||
to be cloned.
|
||||
The implication of this is if you would otherwise be passing _huge_ amounts of data down as props \(Strings that are 10s of kilobytes in size\), you may want to consider turning your child component into a function which returns `Html` that the parent calls, as this means that data does not have to be cloned.
|
||||
|
||||
If you won't need to modify the data passed down through props you can wrap it in an `Rc` so that
|
||||
only a reference-counted pointer to the data is cloned, instead of the actual data itself.
|
||||
If you won't need to modify the data passed down through props you can wrap it in an `Rc` so that only a reference-counted pointer to the data is cloned, instead of the actual data itself.
|
||||
|
||||
## Example
|
||||
|
||||
@ -91,3 +72,4 @@ pub struct LinkProps {
|
||||
active: bool,
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -4,22 +4,19 @@ description: The procedural macro for generating HTML and SVG
|
||||
|
||||
# Using html!
|
||||
|
||||
The `html!` macro allows you to write HTML and SVG code declaratively. It is similar to JSX
|
||||
\(a Javascript extension which allows you to write HTML-like code inside of Javascript\).
|
||||
The `html!` macro allows you to write HTML and SVG code declaratively. It is similar to JSX \(a Javascript extension which allows you to write HTML-like code inside of Javascript\).
|
||||
|
||||
**Important notes**
|
||||
|
||||
1. The `html!` macro only accepts one root html node \(you can counteract this by
|
||||
[using fragments or iterators](lists.md)\)
|
||||
|
||||
[using fragments or iterators](lists.md)\)
|
||||
|
||||
2. An empty `html! {}` invocation is valid and will not render anything
|
||||
3. Literals must always be quoted and wrapped in braces: `html! { "Hello, World" }`
|
||||
|
||||
{% hint style="info" %}
|
||||
The `html!` macro can reach easily the default recursion limit of the compiler. It is advised to bump
|
||||
its value if you encounter compilation errors. Use an attribute like `#![recursion_limit="1024"]`
|
||||
in the crate root (i.e. either `lib.rs` or `main.rs`) to overcome the problem. See the
|
||||
[official documentation](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) and
|
||||
[this Stack Overflow question](https://stackoverflow.com/questions/27454761/what-is-a-crate-attribute-and-where-do-i-add-it)
|
||||
for details.
|
||||
The `html!` macro can reach easily the default recursion limit of the compiler. It is advised to bump its value if you encounter compilation errors. Use an attribute like `#![recursion_limit="1024"]` in the crate root \(i.e. either `lib.rs` or `main.rs`\) to overcome the problem. See the [official documentation](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) and [this Stack Overflow question](https://stackoverflow.com/questions/27454761/what-is-a-crate-attribute-and-where-do-i-add-it) for details.
|
||||
{% endhint %}
|
||||
|
||||
{% page-ref page="lists.md" %}
|
||||
@ -29,3 +26,4 @@ for details.
|
||||
{% page-ref page="literals-and-expressions.md" %}
|
||||
|
||||
{% page-ref page="components.md" %}
|
||||
|
||||
|
||||
@ -63,14 +63,13 @@ impl Component for Container {
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
{% hint style="info" %} Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)]` or manually implementing `Clone` for your type. {% endhint %}
|
||||
{% hint style="info" %}
|
||||
Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)]` or manually implementing `Clone` for your type.
|
||||
{% endhint %}
|
||||
|
||||
## Nested Children with Props
|
||||
|
||||
Nested component properties can be accessed and mutated if the containing component types its children.
|
||||
In the following example, the `List` component can wrap `ListItem` components. 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 in the main yew repository.
|
||||
Nested component properties can be accessed and mutated if the containing component types its children. In the following example, the `List` component can wrap `ListItem` components. 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 in the main yew repository.
|
||||
|
||||
{% code title="parent.rs" %}
|
||||
```rust
|
||||
@ -109,3 +108,4 @@ impl Component for List {
|
||||
}
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
|
||||
@ -43,8 +43,7 @@ html! {
|
||||
{% endtabs %}
|
||||
|
||||
{% hint style="info" %}
|
||||
For convenience, elements which _usually_ require a closing tag are **allowed** to self-close. For
|
||||
example, writing `html! { <div class="placeholder" /> }` is valid.
|
||||
For convenience, elements which _usually_ require a closing tag are **allowed** to self-close. For example, writing `html! { <div class="placeholder" /> }` is valid.
|
||||
{% endhint %}
|
||||
|
||||
## Children
|
||||
@ -152,8 +151,7 @@ html! {
|
||||
|
||||
## Listeners
|
||||
|
||||
Listener attributes need to be passed a `Callback` which is a wrapper around a closure. How you
|
||||
create your callback depends on how you wish your app to react to a listener event:
|
||||
Listener attributes need to be passed a `Callback` which is a wrapper around a closure. How you create your callback depends on how you wish your app to react to a listener event:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Component Handler" %}
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
|
||||
## Fragments
|
||||
|
||||
The `html!` macro always requires a single root node. In order to get around this restriction, it's
|
||||
valid to wrap content in empty tags:
|
||||
The `html!` macro always requires a single root node. In order to get around this restriction, it's valid to wrap content in empty tags:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Valid" %}
|
||||
|
||||
@ -2,11 +2,9 @@
|
||||
|
||||
## Literals
|
||||
|
||||
If expressions resolve to types that implement `Display`, they will be converted to strings and
|
||||
inserted into the DOM as a [Text](https://developer.mozilla.org/en-US/docs/Web/API/Text) node.
|
||||
If expressions resolve to types that implement `Display`, they will be converted to strings and inserted into the DOM as a [Text](https://developer.mozilla.org/en-US/docs/Web/API/Text) node.
|
||||
|
||||
All display text must be enclosed by `{}` blocks because text is handled like an expression. This is
|
||||
the largest deviation from normal HTML syntax that Yew makes.
|
||||
All display text must be enclosed by `{}` blocks because text is handled like an expression. This is the largest deviation from normal HTML syntax that Yew makes.
|
||||
|
||||
```rust
|
||||
let text = "lorem ipsum";
|
||||
@ -39,8 +37,7 @@ html! {
|
||||
}
|
||||
```
|
||||
|
||||
It often makes sense to extract these expressions into functions or closures to optimize for
|
||||
readability:
|
||||
It often makes sense to extract these expressions into functions or closures to optimize for readability:
|
||||
|
||||
```rust
|
||||
let show_link = true;
|
||||
|
||||
@ -6,9 +6,7 @@ description: Yew's official router
|
||||
|
||||
[https://crates.io/crates/yew-router](https://crates.io/crates/yew-router)
|
||||
|
||||
Routers in Single Page Applications \(SPA\) handle displaying different pages depending on what the URL is. Instead of
|
||||
the default behavior of requesting a different remote resource when a link is clicked, the router instead sets the URL
|
||||
locally to point to a valid route in your application. The router then detects this change and then decides what to render.
|
||||
Routers in Single Page Applications \(SPA\) handle displaying different pages depending on what the URL is. Instead of the default behavior of requesting a different remote resource when a link is clicked, the router instead sets the URL locally to point to a valid route in your application. The router then detects this change and then decides what to render.
|
||||
|
||||
## Core Elements
|
||||
|
||||
@ -22,8 +20,7 @@ Communicates with the browser to get and set Routes.
|
||||
|
||||
### RouteAgent
|
||||
|
||||
Owns a RouteService and is used to coordinate updates when the route changes, either from within the application logic
|
||||
or from an event fired from the browser.
|
||||
Owns a RouteService and is used to coordinate updates when the route changes, either from within the application logic or from an event fired from the browser.
|
||||
|
||||
### Switch
|
||||
|
||||
@ -31,16 +28,13 @@ The `Switch` trait is used to convert a `Route` to and from the implementer of t
|
||||
|
||||
### Router
|
||||
|
||||
The Router component communicates with `RouteAgent` and will automatically resolve Routes it gets from the agent into
|
||||
switches, which it will expose via a `render` prop that allows specifying how the resulting switch gets converted to `Html`.
|
||||
The Router component communicates with `RouteAgent` and will automatically resolve Routes it gets from the agent into switches, which it will expose via a `render` prop that allows specifying how the resulting switch gets converted to `Html`.
|
||||
|
||||
## How to use the Router
|
||||
|
||||
First, you want to create a type that represents all the states of your application. Do note that while this typically
|
||||
is an enum, structs are supported as well, and that you can nest other items that implement `Switch` inside.
|
||||
First, you want to create a type that represents all the states of your application. Do note that while this typically is an enum, structs are supported as well, and that you can nest other items that implement `Switch` inside.
|
||||
|
||||
Then you should derive `Switch` for your type. For enums, every variant must be annotated with `#[to = "/some/route"]`,
|
||||
or if you use a struct instead, that must appear outside the struct declaration.
|
||||
Then you should derive `Switch` for your type. For enums, every variant must be annotated with `#[to = "/some/route"]`, or if you use a struct instead, that must appear outside the struct declaration.
|
||||
|
||||
```rust
|
||||
#[derive(Switch)]
|
||||
@ -60,10 +54,7 @@ enum AppRoute {
|
||||
}
|
||||
```
|
||||
|
||||
Do note that the implementation generated by the derive macro for `Switch` will try to match each variant in order from
|
||||
first to last, so if any route could possibly match two of your specified `to` annotations, then the first one will
|
||||
match, and the second will never be tried. For example, if you defined the following `Switch`, the only route that would
|
||||
be matched would be `AppRoute::Home`.
|
||||
Do note that the implementation generated by the derive macro for `Switch` will try to match each variant in order from first to last, so if any route could possibly match two of your specified `to` annotations, then the first one will match, and the second will never be tried. For example, if you defined the following `Switch`, the only route that would be matched would be `AppRoute::Home`.
|
||||
|
||||
```rust
|
||||
#[derive(Switch)]
|
||||
@ -83,16 +74,9 @@ enum AppRoute {
|
||||
}
|
||||
```
|
||||
|
||||
You can also capture sections using variations of `{}` within your `#[to = ""]` annotation. `{}`
|
||||
means capture text until the next separator \(either "/", "?", "&", or "\#" depending on the context\).
|
||||
`{*}` means capture text until the following characters match, or if no characters are present, it
|
||||
will match anything. `{<number>}` means capture text until the specified number of separators are
|
||||
encountered \(example: `{2}` will capture until two separators are encountered\).
|
||||
You can also capture sections using variations of `{}` within your `#[to = ""]` annotation. `{}` means capture text until the next separator \(either "/", "?", "&", or "\#" depending on the context\). `{*}` means capture text until the following characters match, or if no characters are present, it will match anything. `{<number>}` means capture text until the specified number of separators are encountered \(example: `{2}` will capture until two separators are encountered\).
|
||||
|
||||
For structs and enums with named fields, you must specify the field's name within the capture group
|
||||
like so: `{user_name}` or `{*:age}`.
|
||||
For structs and enums with named fields, you must specify the field's name within the capture group like so: `{user_name}` or `{*:age}`.
|
||||
|
||||
The Switch trait works with capture groups that are more structured than just Strings. You can
|
||||
specify any type that implements `Switch`. So you can specify that the capture group is a `usize`,
|
||||
and if the captured section of the URL can't be converted to it, then the variant won't match.
|
||||
The Switch trait works with capture groups that are more structured than just Strings. You can specify any type that implements `Switch`. So you can specify that the capture group is a `usize`, and if the captured section of the URL can't be converted to it, then the variant won't match.
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Build a Sample App
|
||||
|
||||
First create a new Rust library (**important:** create a *library*, not a *binary* by passing the `--lib` flag):
|
||||
First create a new Rust library \(**important:** create a _library_, not a _binary_ by passing the `--lib` flag\):
|
||||
|
||||
```bash
|
||||
cargo new --lib yew-app && cd yew-app
|
||||
@ -20,7 +20,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
yew = "0.16"
|
||||
yew = "0.17"
|
||||
wasm-bindgen = "0.2"
|
||||
```
|
||||
{% endcode %}
|
||||
@ -82,10 +82,7 @@ pub fn run_app() {
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
This template sets up your root `Component`, called `Model` which shows a button that updates itself when you click it.
|
||||
Take special note of `App::<Model>::new().mount_to_body()` inside `main()` which starts your app and mounts it to the
|
||||
page's `<body>` tag. If you would like to start your application with any dynamic properties, you can instead use
|
||||
`App::<Model>::new().mount_to_body_with_props(..)`.
|
||||
This template sets up your root `Component`, called `Model` which shows a button that updates itself when you click it. Take special note of `App::<Model>::new().mount_to_body()` inside `main()` which starts your app and mounts it to the page's `<body>` tag. If you would like to start your application with any dynamic properties, you can instead use `App::<Model>::new().mount_to_body_with_props(..)`.
|
||||
|
||||
Finally, add an `index.html` file into a new folder named `static` in your app.
|
||||
|
||||
@ -112,16 +109,13 @@ mkdir static
|
||||
|
||||
## Run your App!
|
||||
|
||||
Using [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) is the preferred way to get up and
|
||||
running. If you haven't already, install `wasm-pack` with `cargo install wasm-pack` and then build
|
||||
and start a development server by running:
|
||||
Using [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) is the preferred way to get up and running. If you haven't already, install `wasm-pack` with `cargo install wasm-pack` and then build and start a development server by running:
|
||||
|
||||
```bash
|
||||
wasm-pack build --target web --out-name wasm --out-dir ./static
|
||||
```
|
||||
|
||||
`wasm-pack` generates a bundle in the `./static` directory with your app's compiled WebAssembly along
|
||||
with a JavaScript wrapper which will load your application's WebAssembly binary and run it.
|
||||
`wasm-pack` generates a bundle in the `./static` directory with your app's compiled WebAssembly along with a JavaScript wrapper which will load your application's WebAssembly binary and run it.
|
||||
|
||||
Then, use your favorite web server to server the files under `./static`. For example:
|
||||
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
# Choosing between web-sys and stdweb
|
||||
# Choose web-sys or stdweb
|
||||
|
||||
## Introduction
|
||||
|
||||
Yew apps can be built with either [`web-sys`](https://docs.rs/web-sys) or
|
||||
[`stdweb`](https://docs.rs/stdweb). These two crates provide the bindings between Rust and Web APIs.
|
||||
You'll need to choose one or the other when adding `yew` to your cargo dependencies:
|
||||
Yew apps can be built with either [`web-sys`](https://docs.rs/web-sys) or [`stdweb`](https://docs.rs/stdweb). These two crates provide the bindings between Rust and Web APIs. You'll need to choose one or the other when adding `yew` to your cargo dependencies:
|
||||
|
||||
{% code title="Cargo.toml" %}
|
||||
```rust
|
||||
# Choose `web-sys`
|
||||
yew = "0.16"
|
||||
yew = "0.17"
|
||||
|
||||
# Choose `stdweb`
|
||||
yew = { version = "0.16", package = "yew-stdweb" }
|
||||
yew = { version = "0.17", package = "yew-stdweb" }
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
@ -39,44 +37,54 @@ let window = Window::try_from(window_val).expect("conversion to window failed");
|
||||
window.alert("hello from wasm!");
|
||||
```
|
||||
|
||||
The APIs for the two crates differ slightly but they serve roughly the same purpose with similar
|
||||
functionality.
|
||||
The APIs for the two crates differ slightly but they serve roughly the same purpose with similar functionality.
|
||||
|
||||
## Choosing One
|
||||
|
||||
There are a few different angles to consider when choosing between using `web-sys` and `stdweb` for
|
||||
your app. Note that it's possible to use both in one app, but to minimize the binary size of your
|
||||
compiled crate it's best to use only one of the two.
|
||||
|
||||
| | `web-sys` | `stdweb` |
|
||||
| :--- | :--- | :--- |
|
||||
|
||||
|
||||
| Project Status | Actively maintained by the [Rust / Wasm Working Group](https://rustwasm.github.io/) | No Github activity for over 4 months |
|
||||
| :--- | :--- | :--- |
|
||||
|
||||
|
||||
| Web API Coverage | Rust APIs are auto-generated from the Web IDL spec and so should have 100% coverage. | Browser APIs are added as needed by the community |
|
||||
| :--- | :--- | :--- |
|
||||
|
||||
|
||||
| Rust API Design | Takes conservative approach by returning `Result` for most API calls | Often avoids `Result` in favor of panics. For instance, `stdweb::web::window()` will panic when called in a worker. |
|
||||
| :--- | :--- | :--- |
|
||||
|
||||
There are a few different angles to consider when choosing between using `web-sys` and `stdweb` for your app. Note that it's possible to use both in one app, but to minimize the binary size of your compiled crate it's best to use only one of the two.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:left">Supported Build Tools</th>
|
||||
<th style="text-align:left">
|
||||
<th style="text-align:left"></th>
|
||||
<th style="text-align:left"><code>web-sys</code>
|
||||
</th>
|
||||
<th style="text-align:left"><code>stdweb</code>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align:left">Project Status</td>
|
||||
<td style="text-align:left">Actively maintained by the <a href="https://rustwasm.github.io/">Rust / Wasm Working Group</a>
|
||||
</td>
|
||||
<td style="text-align:left">No Github activity for over 8 months</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Web API Coverage</td>
|
||||
<td style="text-align:left">Rust APIs are auto-generated from the Web IDL spec</td>
|
||||
<td style="text-align:left">Browser APIs are added as needed by the community</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Rust API Design</td>
|
||||
<td style="text-align:left">Takes conservative approach by returning <code>Result</code> for most API
|
||||
calls</td>
|
||||
<td style="text-align:left">Often avoids <code>Result</code> in favor of panics. For instance, <code>stdweb::web::window()</code> will
|
||||
panic when called in a worker</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Supported Build Tools</td>
|
||||
<td style="text-align:left">
|
||||
<p></p>
|
||||
<ul>
|
||||
<li><code>wasm-bindgen</code>
|
||||
</li>
|
||||
<li><code>wasm-pack</code>
|
||||
</li>
|
||||
</ul>
|
||||
</th>
|
||||
<th style="text-align:left">
|
||||
</td>
|
||||
<td style="text-align:left">
|
||||
<p></p>
|
||||
<ul>
|
||||
<li><code>cargo-web</code>
|
||||
</li>
|
||||
@ -85,21 +93,17 @@ compiled crate it's best to use only one of the two.
|
||||
<li><code>wasm-pack</code>
|
||||
</li>
|
||||
</ul>
|
||||
</th>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table><table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:left">Supported Targets</th>
|
||||
<th style="text-align:left">
|
||||
<td style="text-align:left">Supported Targets</td>
|
||||
<td style="text-align:left">
|
||||
<ul>
|
||||
<li><code>wasm32-unknown-unknown</code>
|
||||
</li>
|
||||
</ul>
|
||||
</th>
|
||||
<th style="text-align:left">
|
||||
</td>
|
||||
<td style="text-align:left">
|
||||
<ul>
|
||||
<li><code>wasm32-unknown-unknown</code>
|
||||
</li>
|
||||
@ -108,8 +112,8 @@ compiled crate it's best to use only one of the two.
|
||||
<li><code>asmjs-unknown-emscripten</code>
|
||||
</li>
|
||||
</ul>
|
||||
</th>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
# Learn through examples
|
||||
|
||||
The Yew repository is chock-full of [examples](https://github.com/yewstack/yew/tree/v0.16.0/examples)
|
||||
\(in various states of maintenance\). We recommend perusing them to get a feel for how to use
|
||||
different framework features. We also welcome Pull Requests and issues for when they inevitably get
|
||||
neglected and need some ♥️
|
||||
The Yew repository is chock-full of [examples](https://github.com/yewstack/yew/tree/v0.17/examples) \(in various states of maintenance\). We recommend perusing them to get a feel for how to use different framework features. We also welcome Pull Requests and issues for when they inevitably get neglected and need some ♥️
|
||||
|
||||
* [**Todo App** ](https://github.com/yewstack/yew/tree/v0.16.0/examples/todomvc)
|
||||
* [**Custom Components**](https://github.com/yewstack/yew/tree/v0.16.0/examples/custom_components)
|
||||
* [**Multi-threading \(Agents\)**](https://github.com/yewstack/yew/tree/v0.16.0/examples/multi_thread)
|
||||
* [**Timer Service**](https://github.com/yewstack/yew/tree/v0.16.0/examples/timer)
|
||||
* [**Todo App** ](https://github.com/yewstack/yew/tree/v0.17/examples/todomvc)
|
||||
* [**Custom Components**](https://github.com/yewstack/yew/tree/v0.17/examples/custom_components)
|
||||
* [**Multi-threading \(Agents\)**](https://github.com/yewstack/yew/tree/v0.17/examples/multi_thread)
|
||||
* [**Timer Service**](https://github.com/yewstack/yew/tree/v0.17/examples/timer)
|
||||
* [**Nested Components**](https://github.com/yewstack/yew/tree/v0.16.0/examples/nested_list)
|
||||
|
||||
|
||||
@ -6,37 +6,27 @@ description: Set yourself up for success
|
||||
|
||||
## Rust
|
||||
|
||||
First, you'll need Rust. To install Rust and the `cargo` build tool, follow the
|
||||
[official instructions](https://www.rust-lang.org/tools/install).
|
||||
First, you'll need Rust. To install Rust and the `cargo` build tool, follow the [official instructions](https://www.rust-lang.org/tools/install).
|
||||
|
||||
## **Wasm Build Tools**
|
||||
|
||||
Extra tooling is needed to facilitate the interop between WebAssembly and JavaScript. Additionally,
|
||||
depending on the tool you choose, they can help make deployment and packaging much less of a headache
|
||||
by generating all of the wrapper JavaScript code necessary to run the `.wasm` file from your app in the browser.
|
||||
Extra tooling is needed to facilitate the interop between WebAssembly and JavaScript. Additionally, depending on the tool you choose, they can help make deployment and packaging much less of a headache by generating all of the wrapper JavaScript code necessary to run the `.wasm` file from your app in the browser.
|
||||
|
||||
### [**`wasm-pack`**](https://rustwasm.github.io/docs/wasm-pack/)
|
||||
|
||||
A CLI tool developed by the Rust / Wasm Working Group for packaging up WebAssembly. Best used
|
||||
together with the [`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack.
|
||||
A CLI tool developed by the Rust / Wasm Working Group for packaging up WebAssembly. Best used together with the [`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack.
|
||||
|
||||
{% page-ref page="using-wasm-pack.md" %}
|
||||
|
||||
### [**`wasm-bindgen`**](https://rustwasm.github.io/docs/wasm-bindgen/)
|
||||
|
||||
Both a library and CLI tool and is also developed by the Rust / Wasm Working Group. It is a low level
|
||||
tool \(used internally by `wasm-pack`\) which facilitates JS / WebAssembly interoperability. We don't
|
||||
recommend using `wasm-bindgen`directly because it requires hand-writing some JavaScript to bootstrap
|
||||
your WebAssembly binary. However, it is possible and more info can be found on the
|
||||
[**`wasm-bindgen` guide**](https://rustwasm.github.io/docs/wasm-bindgen/).
|
||||
Both a library and CLI tool and is also developed by the Rust / Wasm Working Group. It is a low level tool \(used internally by `wasm-pack`\) which facilitates JS / WebAssembly interoperability. We don't recommend using `wasm-bindgen`directly because it requires hand-writing some JavaScript to bootstrap your WebAssembly binary. However, it is possible and more info can be found on the [**`wasm-bindgen` guide**](https://rustwasm.github.io/docs/wasm-bindgen/).
|
||||
|
||||
{% page-ref page="using-wasm-bindgen.md" %}
|
||||
|
||||
### [**`cargo-web`**](https://github.com/koute/cargo-web)
|
||||
|
||||
The preferred web workflow tool before the introduction of `wasm-pack` and `wasm-bindgen`. It is
|
||||
still the **quickest** way to get up and running and worth installing to run examples that haven't
|
||||
been migrated to support `wasm-pack` yet.
|
||||
The preferred web workflow tool before the introduction of `wasm-pack` and `wasm-bindgen`. It is still the **quickest** way to get up and running and worth installing to run examples that haven't been migrated to support `wasm-pack` yet.
|
||||
|
||||
{% page-ref page="using-cargo-web.md" %}
|
||||
|
||||
@ -142,3 +132,4 @@ been migrated to support `wasm-pack` yet.
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
# Using cargo-web
|
||||
|
||||
Cargo web is a cargo subcommand for building client web apps. It makes building and deploying web
|
||||
applications incredibly easy. It is also the only toolchain that supports Emscripten targets. Read
|
||||
more [here](https://github.com/koute/cargo-web).
|
||||
Cargo web is a cargo subcommand for building client web apps. It makes building and deploying web applications incredibly easy. It is also the only toolchain that supports Emscripten targets. Read more [here](https://github.com/koute/cargo-web).
|
||||
|
||||
**Install**
|
||||
|
||||
@ -10,19 +8,19 @@ more [here](https://github.com/koute/cargo-web).
|
||||
cargo install cargo-web
|
||||
```
|
||||
|
||||
### Build
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cargo web build
|
||||
```
|
||||
|
||||
### Run
|
||||
## Run
|
||||
|
||||
```bash
|
||||
cargo web start
|
||||
```
|
||||
|
||||
### Supported Targets
|
||||
## Supported Targets
|
||||
|
||||
* `wasm32-unknown-unknown`
|
||||
* `wasm32-unknown-emscripten`
|
||||
|
||||
@ -1,31 +1,26 @@
|
||||
# Using wasm-pack
|
||||
|
||||
This tool was created by the Rust / Wasm Working Group and is the most actively developed tool for
|
||||
building WebAssembly applications. It supports packaging code into `npm` modules and has an
|
||||
accompanying [Webpack plugin](https://github.com/wasm-tool/wasm-pack-plugin) for easy integration
|
||||
with an existing JavaScript application. More information is given in
|
||||
[the `wasm-pack` documentation](https://rustwasm.github.io/docs/wasm-pack/introduction.html).
|
||||
This tool was created by the Rust / Wasm Working Group and is the most actively developed tool for building WebAssembly applications. It supports packaging code into `npm` modules and has an accompanying [Webpack plugin](https://github.com/wasm-tool/wasm-pack-plugin) for easy integration with an existing JavaScript application. More information is given in [the `wasm-pack` documentation](https://rustwasm.github.io/docs/wasm-pack/introduction.html).
|
||||
|
||||
{% hint style="info" %}
|
||||
Note that the crate-type in your `Cargo.toml` will need to be `cdylib` when using `wasm-pack`
|
||||
{% endhint %}
|
||||
|
||||
### Install
|
||||
## Install
|
||||
|
||||
```bash
|
||||
cargo install wasm-pack
|
||||
```
|
||||
|
||||
### Build
|
||||
## Build
|
||||
|
||||
This command will produce a bundle in the `./pkg` directory with your app's compiled WebAssembly
|
||||
along with a JavaScript wrapper which can be used to start your application.
|
||||
This command will produce a bundle in the `./pkg` directory with your app's compiled WebAssembly along with a JavaScript wrapper which can be used to start your application.
|
||||
|
||||
```bash
|
||||
wasm-pack build --target web
|
||||
```
|
||||
|
||||
### Bundle
|
||||
## Bundle
|
||||
|
||||
For more information on Rollup visit this [guide](https://rollupjs.org/guide/en/#quick-start)
|
||||
|
||||
@ -33,16 +28,15 @@ For more information on Rollup visit this [guide](https://rollupjs.org/guide/en/
|
||||
rollup ./main.js --format iife --file ./pkg/bundle.js
|
||||
```
|
||||
|
||||
### Serve
|
||||
## Serve
|
||||
|
||||
Feel free to use your preferred server. Here we use a simple python server to serve to
|
||||
[http://\[::1\]:8000](http://[::1]:8000).
|
||||
Feel free to use your preferred server. Here we use a simple python server to serve to
|
||||
|
||||
```bash
|
||||
python -m http.server 8000
|
||||
```
|
||||
|
||||
### Supported Targets
|
||||
## Supported Targets
|
||||
|
||||
* `wasm32-unknown-unknown`
|
||||
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
## `wasm-pack`
|
||||
|
||||
* [Minimal Template](https://github.com/yewstack/yew-wasm-pack-minimal) - Uses `wasm-pack` and
|
||||
`rollup` to build your application, and your own server to serve it. No bells or whistles here.
|
||||
* [Webpack Template](https://github.com/yewstack/yew-wasm-pack-template) - Uses `wasm-pack` and the
|
||||
[`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack to streamline development.
|
||||
|
||||
The important distinction between these templates and using `cargo-web` is that this approach uses a
|
||||
`lib`, not a `bin` crate, and the entry-point to your program is annotated with a `#[wasm_bindgen]` annotation.
|
||||
`rollup` to build your application, and your own server to serve it. No bells or whistles here.
|
||||
|
||||
* [Webpack Template](https://github.com/yewstack/yew-wasm-pack-template) - Uses `wasm-pack` and the
|
||||
|
||||
[`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack to streamline development.
|
||||
|
||||
The important distinction between these templates and using `cargo-web` is that this approach uses a `lib`, not a `bin` crate, and the entry-point to your program is annotated with a `#[wasm_bindgen]` annotation.
|
||||
|
||||
Your `Cargo.toml` also should specify that your crate's type is a "cdylib".
|
||||
|
||||
@ -25,9 +27,9 @@ crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
# for web_sys
|
||||
yew = "0.16"
|
||||
yew = "0.17"
|
||||
# or for stdweb
|
||||
# yew = { version = "0.16", package = "yew-stdweb" }
|
||||
# yew = { version = "0.17", package = "yew-stdweb" }
|
||||
wasm-bindgen = "0.2"
|
||||
```
|
||||
{% endcode %}
|
||||
@ -35,4 +37,6 @@ wasm-bindgen = "0.2"
|
||||
## Other templates
|
||||
|
||||
* [Parcel Template](https://github.com/spielrs/yew-parcel-template) - Created by a community member
|
||||
and uses [Parcel](https://parceljs.org/)
|
||||
|
||||
and uses [Parcel](https://parceljs.org/)
|
||||
|
||||
|
||||
@ -2,5 +2,5 @@
|
||||
|
||||
<TODO>
|
||||
|
||||
A proposal for integrated CSS support can be found here:
|
||||
[https://github.com/yewstack/yew/issues/533](https://github.com/yewstack/yew/issues/533)
|
||||
A proposal for integrated CSS support can be found here: [https://github.com/yewstack/yew/issues/533](https://github.com/yewstack/yew/issues/533)
|
||||
|
||||
|
||||
@ -2,13 +2,11 @@
|
||||
|
||||
## Panics
|
||||
|
||||
Please use the [`console_error_panic`](https://github.com/rustwasm/console_error_panic_hook) crate for nicer stacktraces
|
||||
with Rust symbols. Note, that it is not compatible with apps built with `cargo-web`.
|
||||
Please use the [`console_error_panic`](https://github.com/rustwasm/console_error_panic_hook) crate for nicer stacktraces with Rust symbols. Note, that it is not compatible with apps built with `cargo-web`.
|
||||
|
||||
## Console Logging
|
||||
|
||||
In general, Wasm web apps are able to interact with Browser APIs, and the `console.log` api is no exception. There are
|
||||
a few options available:
|
||||
In general, Wasm web apps are able to interact with Browser APIs, and the `console.log` api is no exception. There are a few options available:
|
||||
|
||||
### [`wasm-logger`](https://crates.io/crates/wasm-logger)
|
||||
|
||||
@ -35,8 +33,7 @@ ConsoleService::new()::info(format!("Update: {:?}", msg));
|
||||
|
||||
## Source Maps
|
||||
|
||||
There is currently no first-class support for source maps for Rust / Wasm web apps. This, of course, is subject to
|
||||
change. If this is no longer true or if progress is made, please suggest a change!
|
||||
There is currently no first-class support for source maps for Rust / Wasm web apps. This, of course, is subject to change. If this is no longer true or if progress is made, please suggest a change!
|
||||
|
||||
### Latest Info
|
||||
|
||||
@ -51,3 +48,4 @@ change. If this is no longer true or if progress is made, please suggest a chang
|
||||
\[2019\] [Rust Wasm roadmap](https://rustwasm.github.io/rfcs/007-2019-roadmap.html#debugging)
|
||||
|
||||
> Debugging is tricky because much of the story is out of this working group's hands, and depends on both the WebAssembly standardization bodies and the folks implementing browser developer tools instead.
|
||||
|
||||
|
||||
@ -10,11 +10,16 @@ Yewtil is a collection of common utilities that help you write Yew programs. It
|
||||
|
||||
* NeqAssign - As discussed earlier, is the best way to assign props to ensure minimal re-rendering.
|
||||
* PureComponents - Components that don't update any of their state. Using NeqAssign under the hood, they act as memoized
|
||||
functions that are called from inside the `html!` macro like normal components are.
|
||||
|
||||
functions that are called from inside the `html!` macro like normal components are.
|
||||
|
||||
* Lrc - linked list reference counted smart pointer functions like `Rc` does, but allows for novel data update patterns.
|
||||
* Mrc/Irc - Mutable/Immutable reference counted smart pointers that function like `Rc` but are more ergonomic to use
|
||||
within Yew, due to implementing `DerefMut` and `BorrowMut`for `Mrc`. This allows `Mrc` to be used with `NeqAssign`.
|
||||
`Irc` acts as an immutable view into the data, which makes this ideal for holding data used in display-only tasks.
|
||||
|
||||
within Yew, due to implementing `DerefMut` and `BorrowMut`for `Mrc`. This allows `Mrc` to be used with `NeqAssign`.
|
||||
|
||||
`Irc` acts as an immutable view into the data, which makes this ideal for holding data used in display-only tasks.
|
||||
|
||||
* History - A history tracking wrapper that uses a `VecDeque` to hold on to previous values that it has represented.
|
||||
* Futures - Support for running futures that send messages to component update loops.
|
||||
* Fetch - Abstractions for handling fetch requests made using `web_sys` and the aforementioned futures feature.
|
||||
|
||||
@ -4,44 +4,42 @@ description: The planned feature roadmap for the Yew framework
|
||||
|
||||
# Roadmap
|
||||
|
||||
### Prioritization
|
||||
## Prioritization
|
||||
|
||||
The prioritization of upcoming features and focuses of the framework are determined by the community. In Spring 2020, a
|
||||
developer survey was sent out to collect feedback on the direction of the project. You can find the summary in the
|
||||
[Yew Wiki](https://github.com/yewstack/yew/wiki/Dev-Survey-%5BSpring-2020%5D).
|
||||
The prioritization of upcoming features and focuses of the framework are determined by the community. In Spring 2020, a developer survey was sent out to collect feedback on the direction of the project. You can find the summary in the [Yew Wiki](https://github.com/yewstack/yew/wiki/Dev-Survey-%5BSpring-2020%5D).
|
||||
|
||||
{% hint style="info" %}
|
||||
Status of all major initiatives can be tracked on the Yew Github [Project board](https://github.com/yewstack/yew/projects)
|
||||
{% endhint %}
|
||||
|
||||
### Focuses
|
||||
## Focuses
|
||||
|
||||
1. Top Requested Features
|
||||
2. Production Readiness
|
||||
3. Documentation
|
||||
4. Pain Points
|
||||
|
||||
#### Top Requested Features
|
||||
### Top Requested Features
|
||||
|
||||
1. [Functional Components](https://github.com/yewstack/yew/projects/3)
|
||||
2. [Component Library](https://github.com/yewstack/yew/projects/4)
|
||||
3. Better state management
|
||||
4. [Server side rendering](https://github.com/yewstack/yew/projects/5)
|
||||
|
||||
#### Production Readiness
|
||||
### Production Readiness
|
||||
|
||||
* Improve Yew test coverage
|
||||
* Reduce binary size
|
||||
* [Benchmark performance](https://github.com/yewstack/yew/issues/5)
|
||||
|
||||
#### Documentation
|
||||
### Documentation
|
||||
|
||||
* Create tutorial
|
||||
* Simplify project setup
|
||||
|
||||
#### Pain Points
|
||||
### Pain Points
|
||||
|
||||
* [Component boilerplate](https://github.com/yewstack/yew/issues/830)
|
||||
* Fetch API
|
||||
* Agents
|
||||
* [Agents](https://github.com/yewstack/yew/projects/6)
|
||||
|
||||
|
||||
@ -8,9 +8,5 @@ description: Testing your app
|
||||
|
||||
## wasm\_bindgen\_test
|
||||
|
||||
The Rust Wasm working group maintains a crate called
|
||||
[`wasm_bindgen_test`](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html) which allows you to run
|
||||
tests in a browser in similar fashion to how the built-in `#[test]` procedural macro works. More information is given
|
||||
in the [Rust WASM working group's documentation](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html)
|
||||
for this module.
|
||||
The Rust Wasm working group maintains a crate called [`wasm_bindgen_test`](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html) which allows you to run tests in a browser in similar fashion to how the built-in `#[test]` procedural macro works. More information is given in the [Rust WASM working group's documentation](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html) for this module.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user