mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
wip: update readme
This commit is contained in:
parent
55e6dd9701
commit
9bd56ee499
4 changed files with 149 additions and 23 deletions
143
README.md
143
README.md
|
@ -199,6 +199,149 @@ You shouldn't use Dioxus if:
|
|||
- You want to support browsers where Wasm or asm.js are not supported.
|
||||
|
||||
|
||||
## Show me some examples!
|
||||
|
||||
In our collection of examples, guides, and tutorials, we have:
|
||||
- The book (an introductory course)
|
||||
- The guide (an in-depth analysis of everything in Dioxus)
|
||||
- The reference (a collection of examples with heavy documentation)
|
||||
- The general examples
|
||||
- The platform-specific examples (web, ssr, desktop, mobile, server)
|
||||
|
||||
Here's what a few common tasks look like in Dioxus:
|
||||
|
||||
Nested components with children and internal state:
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
cx.render(rsx!( Toggle { "Toggle me" } ))
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Props)]
|
||||
struct ToggleProps { children: Element }
|
||||
|
||||
fn Toggle(cx: Context, props: &ToggleProps) -> Element {
|
||||
let mut toggled = use_state(cx, || false);
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
{&props.children}
|
||||
button { onclick: move |_| toggled.set(true),
|
||||
{toggled.and_then(|| "On").or_else(|| "Off")}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Controlled inputs:
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let value = use_state(cx, String::new);
|
||||
cx.render(rsx!(
|
||||
input {
|
||||
"type": "text",
|
||||
value: "{value}",
|
||||
oninput: move |evt| value.set(evt.value.clone())
|
||||
}
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
Lists and Conditional rendering:
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let list = (0..10).map(|i| {
|
||||
rsx!(li { key: "{i}", "Value: {i}" })
|
||||
});
|
||||
|
||||
let title = match list.len() {
|
||||
0 => rsx!("Not enough"),
|
||||
_ => rsx!("Plenty!"),
|
||||
};
|
||||
|
||||
if should_show {
|
||||
cx.render(rsx!(
|
||||
{title}
|
||||
ul { {list} }
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Tiny components:
|
||||
```rust
|
||||
static App: FC<()> = |cx, _| rsx!(cx, div {"hello world!"});
|
||||
```
|
||||
|
||||
Borrowed prop contents:
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let name = use_state(cx, || String::from("example"));
|
||||
rsx!(cx, Child { title: name.as_str() })
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
struct ChildProps<'a> { title: &'a str }
|
||||
|
||||
fn Child(cx: Context, props: &ChildProps) -> Element {
|
||||
rsx!(cx, "Hello {props.title}")
|
||||
}
|
||||
```
|
||||
|
||||
Global State
|
||||
```rust
|
||||
struct GlobalState { name: String }
|
||||
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
use_provide_shared_state(cx, || GlobalState { name: String::from("Toby") })
|
||||
rsx!(cx, Leaf {})
|
||||
}
|
||||
|
||||
fn Leaf(cx: Context, props: &()) -> Element {
|
||||
let state = use_consume_shared_state::<GlobalState>(cx)?;
|
||||
rsx!(cx, "Hello {state.name}")
|
||||
}
|
||||
```
|
||||
|
||||
Router (inspired by Yew-Router)
|
||||
```rust
|
||||
#[derive(PartialEq, Clone, Hash, Eq, Routable)]
|
||||
enum Route {
|
||||
#[at("/")]
|
||||
Home,
|
||||
#[at("/post/{id}")]
|
||||
Post(id)
|
||||
}
|
||||
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let route = use_router(cx, Route::parse);
|
||||
cx.render(rsx!(div {
|
||||
{match route {
|
||||
Route::Home => rsx!( Home {} ),
|
||||
Route::Post(id) => rsx!( Post { id: id })
|
||||
}}
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
Suspense
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let doggo = use_suspense(cx,
|
||||
|| async { reqwest::get("https://dog.ceo/api/breeds/image/random").await.unwrap().json::<Response>().await.unwrap() },
|
||||
|response| cx.render(rsx!( img { src: "{response.message}" }))
|
||||
);
|
||||
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
"One doggo coming right up:"
|
||||
{doggo}
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT license].
|
||||
|
|
|
@ -365,7 +365,6 @@ impl<'bump> DiffState<'bump> {
|
|||
|
||||
fn create_text_node(&mut self, vtext: &'bump VText<'bump>, node: &'bump VNode<'bump>) {
|
||||
let real_id = self.scopes.reserve_node(node);
|
||||
let parent = self.stack.element_stack.last().unwrap();
|
||||
|
||||
self.mutations.create_text_node(vtext.text, real_id);
|
||||
vtext.dom_id.set(Some(real_id));
|
||||
|
@ -413,7 +412,6 @@ impl<'bump> DiffState<'bump> {
|
|||
let real_id = self.scopes.reserve_node(node);
|
||||
self.stack.element_stack.push(real_id);
|
||||
dom_id.set(Some(real_id));
|
||||
log::debug!("Parent ID for {:?} set to {:?}", real_id, parent_id.get());
|
||||
|
||||
self.mutations.create_element(tag_name, *namespace, real_id);
|
||||
|
||||
|
@ -545,7 +543,7 @@ impl<'bump> DiffState<'bump> {
|
|||
&mut self,
|
||||
old: &'bump VText<'bump>,
|
||||
new: &'bump VText<'bump>,
|
||||
old_node: &'bump VNode<'bump>,
|
||||
_old_node: &'bump VNode<'bump>,
|
||||
new_node: &'bump VNode<'bump>,
|
||||
) {
|
||||
if let Some(root) = old.dom_id.get() {
|
||||
|
|
|
@ -261,9 +261,7 @@ pub struct VAnchor {
|
|||
/// A bump-allocated string slice and metadata.
|
||||
pub struct VText<'src> {
|
||||
pub text: &'src str,
|
||||
|
||||
pub dom_id: Cell<Option<ElementId>>,
|
||||
|
||||
pub is_static: bool,
|
||||
}
|
||||
|
||||
|
@ -276,20 +274,12 @@ pub struct VFragment<'src> {
|
|||
/// An element like a "div" with children, listeners, and attributes.
|
||||
pub struct VElement<'a> {
|
||||
pub tag_name: &'static str,
|
||||
|
||||
pub namespace: Option<&'static str>,
|
||||
|
||||
pub key: Option<&'a str>,
|
||||
|
||||
pub dom_id: Cell<Option<ElementId>>,
|
||||
|
||||
// Keep the parent id around so we can bubble events through the tree
|
||||
pub parent_id: Cell<Option<ElementId>>,
|
||||
|
||||
pub listeners: &'a [Listener<'a>],
|
||||
|
||||
pub attributes: &'a [Attribute<'a>],
|
||||
|
||||
pub children: &'a [VNode<'a>],
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ use fxhash::FxHashSet;
|
|||
use indexmap::IndexSet;
|
||||
use smallvec::SmallVec;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::task::Poll;
|
||||
use std::{any::Any, collections::VecDeque};
|
||||
|
@ -293,6 +292,7 @@ impl VirtualDom {
|
|||
|
||||
let mut items = scope.items.borrow_mut();
|
||||
|
||||
// really this should just be retain_mut but that doesn't exist yet
|
||||
while let Some(mut task) = items.tasks.pop() {
|
||||
// todo: does this make sense?
|
||||
// I don't usually write futures by hand
|
||||
|
@ -312,9 +312,7 @@ impl VirtualDom {
|
|||
scopes_to_clear.push(*fut);
|
||||
}
|
||||
|
||||
for task in unfinished_tasks.drain(..) {
|
||||
items.tasks.push(task);
|
||||
}
|
||||
items.tasks.extend(unfinished_tasks.drain(..));
|
||||
}
|
||||
|
||||
for scope in scopes_to_clear {
|
||||
|
@ -461,17 +459,14 @@ impl VirtualDom {
|
|||
);
|
||||
diff_state.stack.push(DiffInstruction::Diff { new, old });
|
||||
diff_state.stack.scope_stack.push(scopeid);
|
||||
|
||||
let scope = scopes.get_scope(&scopeid).unwrap();
|
||||
let container = scope.container;
|
||||
log::debug!("scope {:?} container {:?}", scope.our_arena_idx, container);
|
||||
diff_state.stack.element_stack.push(container);
|
||||
diff_state.stack.element_stack.push(scope.container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let work_completed = diff_state.work(&mut deadline);
|
||||
|
||||
if work_completed {
|
||||
if diff_state.work(&mut deadline) {
|
||||
let DiffState {
|
||||
mutations,
|
||||
seen_scopes,
|
||||
|
|
Loading…
Reference in a new issue