浏览代码

docs: add more docs

Jonathan Kelley 3 年之前
父节点
当前提交
1560e2daca

+ 1 - 0
docs/guide/.vscode/spellright.dict

@@ -1,2 +1,3 @@
 oninput
 oninput
 Webview
 Webview
+idanarye

+ 4 - 3
docs/guide/src/SUMMARY.md

@@ -9,9 +9,10 @@
   - [Lists](elements/lists.md)
   - [Lists](elements/lists.md)
   - [Special Attributes](elements/special_attributes.md)
   - [Special Attributes](elements/special_attributes.md)
 - [Components](elements/components.md)
 - [Components](elements/components.md)
-  - [Component Properties](elements/propsmacro.md)
-  - [Reusing, Importing, and Exporting Components](elements/exporting_components.md)
-  - [Component Children and Attributes](elements/component_children.md)
+  - [Properties](elements/propsmacro.md)
+  - [Reusing, Importing, and Exporting](elements/exporting_components.md)
+  - [Children and Attributes](elements/component_children.md)
+  - [Composing Components](elements/composing.md)
 - [Adding Interactivity](interactivity/index.md)
 - [Adding Interactivity](interactivity/index.md)
   - [Hooks and Internal State](interactivity/hooks.md)
   - [Hooks and Internal State](interactivity/hooks.md)
   - [Event handlers](interactivity/event_handlers.md)
   - [Event handlers](interactivity/event_handlers.md)

+ 3 - 0
docs/guide/src/async/fetching.md

@@ -1 +1,4 @@
 # Fetching
 # Fetching
+
+
+This section is currently under construction! 🏗

+ 3 - 0
docs/guide/src/async/index.md

@@ -17,3 +17,6 @@ Writing apps that deal with Send/Sync can be frustrating at times. Under the hoo
 
 
 
 
 All async code in your app is polled on a `LocalSet`, so any async code we w
 All async code in your app is polled on a `LocalSet`, so any async code we w
+
+
+> This section is currently under construction! 🏗

+ 43 - 0
docs/guide/src/elements/composing.md

@@ -0,0 +1,43 @@
+# Composing Components
+
+So far, we've talked about declaring new components and setting up their properties. However, we haven't really talked about how components work together and how your app is updated.
+
+In this section, we'll talk about:
+
+- Sharing data between components
+- How the UI is updated from input and state changes
+- Forcing renders
+- How renders propagate
+- 
+
+
+### Rendering our posts with a PostList component
+
+Let's start by modeling this problem with a component and some properties. 
+
+For this example, we're going to use the borrowed component syntax since we probably have a large list of posts that we don't want to clone every time we render the Post List.
+
+```rust
+#[derive(Props, PartialEq)]
+struct PostListProps<'a> {
+    posts: &'a [PostData]
+}
+```
+Next, we're going to define our component:
+
+```rust
+fn App(cx: Scope<PostList>) -> Element {
+    cx.render(rsx!{
+        ul { class: "post-list",
+            // we can drop an iterator directly into our elements
+            cx.props.posts.iter().map(|post| rsx!{
+                Post {
+                    title: post.title,
+                    age: post.age,
+                    original_poster: post.original_poster
+                }
+            })
+        }
+    })
+}
+```

+ 12 - 33
docs/guide/src/elements/lists.md

@@ -45,10 +45,21 @@ Finally, we can include this list in the final structure:
 ```rust
 ```rust
 rsx!(
 rsx!(
     ul {
     ul {
-        {name_list}
+        name_list
     }
     }
 )
 )
 ```
 ```
+Or, we can include the iterator inline:
+```rust
+rsx!(
+    ul {
+        names.iter().map(|name| rsx!(
+            li { "{name}" } 
+        ))
+    }
+)
+```
+
 The HTML-rendered version of this list would follow what you would expect:
 The HTML-rendered version of this list would follow what you would expect:
 ```html
 ```html
 <ul>
 <ul>
@@ -59,38 +70,6 @@ The HTML-rendered version of this list would follow what you would expect:
 </ul>
 </ul>
 ```
 ```
 
 
-### Rendering our posts with a PostList component
-
-Let's start by modeling this problem with a component and some properties. 
-
-For this example, we're going to use the borrowed component syntax since we probably have a large list of posts that we don't want to clone every time we render the Post List.
-
-```rust
-#[derive(Props, PartialEq)]
-struct PostListProps<'a> {
-    posts: &'a [PostData]
-}
-```
-Next, we're going to define our component:
-
-```rust
-fn App(cx: Scope<PostList>) -> Element {
-    cx.render(rsx!{
-        ul { class: "post-list",
-            // we can drop an iterator directly into our elements
-            cx.props.posts.iter().map(|post| rsx!{
-                Post {
-                    title: post.title,
-                    age: post.age,
-                    original_poster: post.original_poster
-                }
-            })
-        }
-    })
-}
-```
-
-
 ## Filtering Iterators
 ## Filtering Iterators
 
 
 Rust's iterators are extremely powerful, especially when used for filtering tasks. When building user interfaces, you might want to display a list of items filtered by some arbitrary check.
 Rust's iterators are extremely powerful, especially when used for filtering tasks. When building user interfaces, you might want to display a list of items filtered by some arbitrary check.

+ 145 - 0
docs/guide/src/elements/propsmacro.md

@@ -9,6 +9,151 @@ All component `properties` must implement the `Properties` trait. The `Props` ma
 
 
 
 
 
 
+## Using the Props Macro
+
+All `properties` that your components take must implement the `Properties` trait. The simplest props you can use is simply `()` - or no value at all. `Scope` is generic over your component's props and actually defaults to `()`.
+
+```rust
+// this scope
+Scope<()> 
+
+// is the same as this scope
+Scope
+```
+
+If we wanted to define a component with its own props, we would create a new struct and tack on the `Props` derive macro:
+
+```rust
+#[derive(Props)]
+struct MyProps {
+    name: String
+}
+```
+This particular code will not compile - all `Props` must either a) borrow from their parent or b) implement `PartialEq`. Since our props do not borrow from their parent, they are `'static` and must implement PartialEq.
+
+For an owned example:
+```rust
+#[derive(Props, PartialEq)]
+struct MyProps {
+    name: String
+}
+```
+
+For a borrowed example:
+```rust
+#[derive(Props)]
+struct MyProps<'a> {
+    name: &'a str
+}
+```
+
+Then, to use these props in our component, we simply swap out the generic parameter on scope.
+
+For owned props, we just drop it in:
+
+```rust
+fn Demo(cx: Scope<MyProps>) -> Element {
+    todo!()
+}
+```
+
+However, for props that borrow data, we need to explicitly declare lifetimes. Rust does not know that our props and our component share the same lifetime, so must explicitly attach a lifetime in two places:
+
+```rust
+fn Demo<'a>(cx: Scope<'a, MyProps<'a>>) -> Element {
+    todo!()
+}
+```
+
+By putting the `'a` lifetime on Scope and our Props, we can now borrow data from our parent and pass it on to our children.
+
+
+## Memoization
+
+If you're coming from React, you might be wondering how memoization fits in. For our purpose, memoization is the process in which we check if a component actually needs to be re-rendered when its props change. If a component's properties change but they wouldn't necessarily affect the output, then we don't need to actually re-render the component.
+
+For example, let's say we have a component that has two children:
+
+```rust
+fn Demo(cx: Scope) -> Element {
+    let name = use_state(&cx, || String::from("bob"));
+    let age = use_state(&cx, || 21);
+
+    cx.render(rsx!{
+        Name { name: name }
+        Age { age: age }
+    })
+}
+```
+
+If `name` changes but `age` does not, then there is no reason to re-render our `Age` component since the contents of its props did not meaningfully change.
+
+
+Dioxus implements memoization by default, which means you can always rely on props with `PartialEq` or no props at all to act as barriers in your app. This can be extremely useful when building larger apps where properties frequently change. By moving our state into a global state management solution, we can achieve precise, surgical re-renders, improving the performance of our app.
+
+
+However, for components that borrow values from their parents, we cannot safely memoize them.
+
+For example, this component borrows `&str` - and if the parent re-renders, then the actual reference to `str` will probably be different. Since the data is borrowed, we need to pass a new version down the tree.
+
+```rust
+#[derive(Props)]
+struct MyProps<'a> {
+    name: &'a str
+}
+
+fn Demo<'a>(cx: Scope<'a, MyProps<'a>>) -> Element {
+    todo!()
+}
+```
+
+TLDR: 
+- if you see props with a lifetime or generics, it cannot be memoized
+- memoization is done automatically through the `PartialEq` trait
+- components with empty props can act as memoization barriers
+
+## Optional Fields
+
+Dioxus' `Props` macro is very similar to [@idanarye](https://github.com/idanarye)'s [TypedBuilder crate](https://github.com/idanarye/rust-typed-builder) and supports many of the same parameters.
+
+For example, you can easily create optional fields by attaching the `optional` modifier to a field.
+
+```rust
+#[derive(Props, PartialEq)]
+struct MyProps {
+    name: String,
+
+    #[props(optional)]
+    description: Option<String>
+}
+
+fn Demo(cx: MyProps) -> Element {
+    ...
+}
+```
+
+Then, we can completely omit the description field when calling the component:
+
+```rust
+rsx!{
+    Demo {
+        name: "Thing".to_string(),
+        // description is omitted
+    }
+}
+```
+
+The `optional` modifier is a combination of two separate modifiers: `default` and `strip_option`. The full list of modifiers includes:
+
+- `default` - automatically add the field using its `Default` implementation
+- `strip_option` - automatically wrap values at the call site in `Some`
+- `optional` - combine both `default` and `strip_option`
+- `into` - automatically call `into` on the value at the callsite
+
+For more information on how tags work, check out the [TypedBuilder](https://github.com/idanarye/rust-typed-builder) crate. However, all attributes for props in Dioxus are flattened (no need for `setter` syntax) and the `optional` field is new.
+
+
+
 
 
 ## The inline_props macro
 ## The inline_props macro
 
 

+ 17 - 8
docs/guide/src/elements/special_attributes.md

@@ -30,9 +30,7 @@ fn BlogPost(cx: Scope) -> Element {
 }
 }
 ```
 ```
 
 
-> Note! 
-
-This attribute is called "dangerous_inner_html" because it is DANGEROUS. If you're not careful, you can easily expose cross-site-scripting (XSS) attacks to your users. If you're handling untrusted input, make sure to escape your HTML before passing it into `dangerous_inner_html`.
+> Note! This attribute is called "dangerous_inner_html" because it is DANGEROUS. If you're not careful, you can easily expose cross-site-scripting (XSS) attacks to your users. If you're handling untrusted input, make sure to escape your HTML before passing it into `dangerous_inner_html`.
 
 
 
 
 ## Boolean Attributes
 ## Boolean Attributes
@@ -87,13 +85,13 @@ Not all attributes work like this however. Only *these specific attributes* are
 
 
 For any other attributes, a value of `"false"` will be sent directly to the DOM.
 For any other attributes, a value of `"false"` will be sent directly to the DOM.
 
 
-## `prevent_default`
+## Stopping form input and navigation with `prevent_default`
 
 
-Currently, preventing default on events from an event handler is not possible from Desktop/Mobile. Until this is supported, it's possible to prevent default using the `prevent_default` attribute. 
+Currently, calling `prevent_default` on events in EventHandlers is not possible from Desktop/Mobile. Until this is supported, it's possible to prevent default using the `prevent_default` attribute. 
 
 
 > Note: you cannot conditionally prevent default with this approach. This is a limitation until synchronous event handling is available across the Webview boundary 
 > Note: you cannot conditionally prevent default with this approach. This is a limitation until synchronous event handling is available across the Webview boundary 
 
 
-To use `prevent_default`, simple use the `prevent_default` attribute and set it to the name of the event handler you want to prevent default on. We can attach this attribute multiple times for multiple attributes.
+To use `prevent_default`, simply attach the `prevent_default` attribute to a given element and set it to the name of the event handler you want to prevent default on. We can attach this attribute multiple times for multiple attributes.
 
 
 ```rust
 ```rust
 rsx!{
 rsx!{
@@ -107,7 +105,7 @@ rsx!{
 }
 }
 ```
 ```
 
 
-## `..Attributes`
+## Passing attributes into children: `..Attributes`
 
 
 Just like Dioxus supports spreading component props into components, we also support spreading attributes into elements. This lets you pass any arbitrary attributes through components into elements.
 Just like Dioxus supports spreading component props into components, we also support spreading attributes into elements. This lets you pass any arbitrary attributes through components into elements.
 
 
@@ -131,7 +129,6 @@ pub fn StateInput<'a>(cx: Scope<'a, InputProps<'a>>) -> Element {
 
 
 ## Controlled inputs and `value`, `checked`, and `selected`
 ## Controlled inputs and `value`, `checked`, and `selected`
 
 
-
 In Dioxus, there is a distinction between controlled and uncontrolled inputs. Most inputs you'll use are "controlled," meaning we both drive the `value` of the input and react to the `oninput`.
 In Dioxus, there is a distinction between controlled and uncontrolled inputs. Most inputs you'll use are "controlled," meaning we both drive the `value` of the input and react to the `oninput`.
 
 
 Controlled components:
 Controlled components:
@@ -179,3 +176,15 @@ rsx!{
 ```
 ```
 
 
 ## Wrapping up
 ## Wrapping up
+
+We've reached just about the end of what you can do with elements without venturing into "advanced" territory.
+
+In this chapter, we learned:
+- How to declare elements
+- How to conditionally render parts of your UI
+- How to render lists
+- Which attributes are "special"
+
+There's more to elements! For further reading, check out:
+
+- [Custom Elements]()

+ 2 - 0
docs/guide/src/interactivity/event_handlers.md

@@ -1 +1,3 @@
 # Event handlers
 # Event handlers
+
+> This section is currently under construction! 🏗

+ 2 - 0
docs/guide/src/interactivity/lifecycles.md

@@ -1 +1,3 @@
 # Lifecycle, updates, and effects
 # Lifecycle, updates, and effects
+
+> This section is currently under construction! 🏗

+ 3 - 0
docs/guide/src/interactivity/user_input.md

@@ -1,3 +1,6 @@
 # User Input and Controlled Components
 # User Input and Controlled Components
 
 
 Handling user input is one of the most common things your app will do, but it can be tricky
 Handling user input is one of the most common things your app will do, but it can be tricky
+
+
+> This section is currently under construction! 🏗

+ 1 - 0
docs/guide/src/state/errorhandling.md

@@ -9,3 +9,4 @@ fn App((cx, props): Component) -> Element {
 }
 }
 ```
 ```
 
 
+> This section is currently under construction! 🏗

+ 1 - 0
docs/guide/src/state/index.md

@@ -7,6 +7,7 @@ In this chapter, we'll cover the various ways to manage state, the appropriate t
 ## Terminology 
 ## Terminology 
 
 
 
 
+> This section is currently under construction! 🏗
 
 
 
 
 
 

+ 3 - 0
docs/guide/src/state/liftingstate.md

@@ -1 +1,4 @@
 # Lifting State
 # Lifting State
+
+
+> This section is currently under construction! 🏗

+ 3 - 0
docs/guide/src/state/localstate.md

@@ -1 +1,4 @@
 # Local State
 # Local State
+
+
+> This section is currently under construction! 🏗

+ 6 - 0
docs/guide/src/state/sharedstate.md

@@ -1 +1,7 @@
 # Global State
 # Global State
+
+
+cx.provide_context()
+cx.consume_context()
+
+> This section is currently under construction! 🏗

+ 2 - 0
docs/guide/src/tutorial/components.md

@@ -1 +1,3 @@
 # Defining Components
 # Defining Components
+
+This section is currently under construction! 🏗

+ 2 - 0
docs/guide/src/tutorial/state.md

@@ -1 +1,3 @@
 # Defining State
 # Defining State
+
+This section is currently under construction! 🏗

+ 3 - 0
docs/guide/src/tutorial/structure.md

@@ -1 +1,4 @@
 # Structuring our app
 # Structuring our app
+
+
+This section is currently under construction! 🏗

+ 3 - 0
docs/guide/src/tutorial/styling.md

@@ -1 +1,4 @@
 # Styling
 # Styling
+
+
+This section is currently under construction! 🏗