Docs: more examples and docs
This commit is contained in:
parent
100a78f321
commit
7fbaf69cab
41
README.md
41
README.md
|
@ -89,3 +89,44 @@ TypeScript is a great addition to JavaScript, but comes with a lot of tweaking f
|
|||
- various macros (`html!`, `rsx!`) for fast template iteration
|
||||
|
||||
And much more. Dioxus makes Rust apps just as fast to write as React apps, but affords more robustness, giving your frontend team greater confidence in making big changes in shorter time. Dioxus also works on the server, on the web, on mobile, on desktop - and it runs completely natively so performance is never an issue.
|
||||
|
||||
# Parity with React
|
||||
|
||||
Sorted by priority
|
||||
|
||||
| Feature | Dioxus | React | Notes |
|
||||
| ---------------------- | ------ | ----- | ------------------------------------------------ |
|
||||
| ----- Phase 1 ----- | ----- | ----- | ----- |
|
||||
| Conditional Rendering | ✅ | ✅ | if/then to hide/show component |
|
||||
| Map, Iterator | ✅ | ✅ | map/filter/reduce rsx! |
|
||||
| Keyed Components | ✅ | ✅ | advanced diffing with keys |
|
||||
| Web | ✅ | ✅ | renderer for web browser |
|
||||
| Desktop (webview) | ✅ | ✅ | renderer for desktop |
|
||||
| Context | ✅ | ✅ | share state through the tree |
|
||||
| Hook | ✅ | ✅ | memory cells in components |
|
||||
| SSR | ✅ | ✅ | render directly to string |
|
||||
| Runs natively | ✅ | 👀 | runs as a portable binary w/o a runtime (Node) |
|
||||
| Component Children | ✅ | ✅ | cx.children() as a list of nodes |
|
||||
| Null components | ✅ | ✅ | allow returning no components |
|
||||
| No-div components | ✅ | ✅ | components that render components |
|
||||
| Fragments | ✅ | ✅ | rsx! can return multiple elements without a root |
|
||||
| Manual Props | 👀 | ✅ | Manually pass in props |
|
||||
| NodeRef | 👀 | ✅ | gain direct access to nodes |
|
||||
| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs |
|
||||
| CSS/Inline Styles | 🛠 | ✅ | syntax for inline/conditional styles |
|
||||
| 1st class global state | 🛠 | ✅ | redux/recoil/mobx on top of context |
|
||||
| ----- Phase 2 ----- | ----- | ----- | ----- |
|
||||
| 1st class router | 👀 | ✅ | Hook built on top of history |
|
||||
| Assets | 👀 | ✅ | include css/svg/img url statically |
|
||||
| Integrated classnames | 🛠 | 👀 | built-in `classnames` |
|
||||
| Suspense | 👀 | 👀 | schedule future render from future/promise |
|
||||
| Transition | 👀 | 👀 | High-level control over suspense |
|
||||
| Animation | 👀 | ✅ | Spring-style animations |
|
||||
| Mobile | 👀 | ✅ | Render with cacao |
|
||||
| Desktop (native) | 👀 | ✅ | Render with native desktop |
|
||||
| 3D Renderer | 👀 | ✅ | react-three-fiber |
|
||||
| ----- Phase 3 ----- | ----- | ----- | ----- |
|
||||
| Portal | 👀 | ✅ | cast elements through tree |
|
||||
| Error/Panic boundary | 👀 | ✅ | catch panics and display custom BSOD |
|
||||
| Code-splitting | 👀 | ✅ | Make bundle smaller/lazy |
|
||||
| LiveView | 👀 | 👀 | Example for SSR + WASM apps |
|
||||
|
|
|
@ -2,13 +2,7 @@
|
|||
|
||||
use dioxus_core::prelude::*;
|
||||
|
||||
fn main() {
|
||||
Some(10)
|
||||
.map(|f| f * 5)
|
||||
.map(|f| f / 3)
|
||||
.map(|f| f * 5)
|
||||
.map(|f| f / 3);
|
||||
}
|
||||
fn main() {}
|
||||
|
||||
static Example: FC<()> = |ctx| {
|
||||
let (name, set_name) = use_state(&ctx, || "...?");
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
//!
|
||||
//! A full in-depth reference guide is available at: https://www.notion.so/rsx-macro-basics-ef6e367dec124f4784e736d91b0d0b19
|
||||
//!
|
||||
//! ## Topics
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//! ### Elements
|
||||
//! - Create any element from its tag
|
||||
//! - Accept compile-safe attributes for each tag
|
||||
|
@ -46,23 +42,119 @@ fn main() {
|
|||
dioxus::webview::launch(Example);
|
||||
}
|
||||
|
||||
/// When trying to return "nothing" to Dioxus, you'll need to specify the type parameter or Rust will be sad.
|
||||
/// This type alias specifices the type for you so you don't need to write "None as Option<()>"
|
||||
const NONE_ELEMENT: Option<()> = None;
|
||||
|
||||
use baller::Baller;
|
||||
use dioxus_core::prelude::*;
|
||||
|
||||
static Example: FC<()> = |ctx| {
|
||||
ctx.render(rsx! {
|
||||
static Example: FC<()> = |cx| {
|
||||
let formatting = "formatting!";
|
||||
let formatting_tuple = ("a", "b");
|
||||
let lazy_fmt = format_args!("lazily formatted text");
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
// Elements
|
||||
div {}
|
||||
h1 {"Some text"}
|
||||
h1 {"Some text with {formatting}"}
|
||||
h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
|
||||
h2 {
|
||||
"Multiple"
|
||||
"Text"
|
||||
"Blocks"
|
||||
"Use comments as separators in html"
|
||||
}
|
||||
div {
|
||||
h1 {"multiple"}
|
||||
h2 {"nested"}
|
||||
h3 {"elements"}
|
||||
}
|
||||
div {
|
||||
class: "my special div"
|
||||
h1 {"Headers and attributes!"}
|
||||
}
|
||||
div {
|
||||
// pass simple rust expressions in
|
||||
class: lazy_fmt,
|
||||
id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
|
||||
div {
|
||||
class: {
|
||||
const WORD: &str = "expressions";
|
||||
format_args!("Arguments can be passed in through curly braces for complex {}", WORD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expressions can be used in element position too:
|
||||
{rsx!(p { "More templating!" })}
|
||||
{html!(<p>"Even HTML templating!!"</p>)}
|
||||
|
||||
// Iterators
|
||||
{(0..10).map(|i| rsx!(li { "{i}" }))}
|
||||
{{
|
||||
let data = std::collections::HashMap::<&'static str, &'static str>::new();
|
||||
// Iterators *should* have keys when you can provide them.
|
||||
// Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
|
||||
// Using an "ID" associated with your data is a good idea.
|
||||
data.into_iter().map(|(k, v)| rsx!(li { key: "{k}" "{v}" }))
|
||||
}}
|
||||
|
||||
|
||||
// Matching
|
||||
// Matching will throw a Rust error about "no two closures are the same type"
|
||||
// To fix this, call "render" method or use the "in" syntax to produce VNodes.
|
||||
// There's nothing we can do about it, sorry :/ (unless you want *really* unhygenic macros)
|
||||
{match true {
|
||||
true => rsx!(in cx, h1 {"Top text"}),
|
||||
false => cx.render(rsx!( h1 {"Bottom text"}))
|
||||
}}
|
||||
|
||||
// ==============
|
||||
// Components
|
||||
// ==============
|
||||
// Conditional rendering
|
||||
// Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
|
||||
// You can convert a bool condition to rsx! with .then and .or
|
||||
{true.then(|| rsx!(div {}))}
|
||||
|
||||
// True conditions need to be rendered (same reasons as matching)
|
||||
{if true {
|
||||
rsx!(in cx, h1 {"Top text"})
|
||||
} else {
|
||||
cx.render(rsx!( h1 {"Bottom text"}))
|
||||
}}
|
||||
|
||||
// returning "None" is a bit noisy... but rare in practice
|
||||
{None as Option<()>}
|
||||
|
||||
// Use the Dioxus type-alias for less noise
|
||||
{NONE_ELEMENT}
|
||||
|
||||
// can also just use empty fragments
|
||||
Fragment {}
|
||||
|
||||
// Fragments let you insert groups of nodes without a parent.
|
||||
// This lets you make components that insert elements as siblings without a container.
|
||||
div {"A"}
|
||||
Fragment {
|
||||
div {"B"}
|
||||
div {"C"}
|
||||
Fragment {
|
||||
"D"
|
||||
Fragment {
|
||||
"heavily nested fragments is an antipattern"
|
||||
"they cause Dioxus to do unnecessary work"
|
||||
"don't use them carelessly if you can help it"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Components
|
||||
// Can accept any paths
|
||||
crate::baller::Baller {}
|
||||
// Notice how you still get syntax highlighting and IDE support :)
|
||||
Baller {}
|
||||
baller::Baller { }
|
||||
crate::baller::Baller {}
|
||||
|
||||
// Can take properties
|
||||
Taller { a: "asd" }
|
||||
|
@ -71,10 +163,14 @@ static Example: FC<()> = |ctx| {
|
|||
Taller { a: "asd" }
|
||||
|
||||
// Can pass in props directly
|
||||
Taller { a: "asd" /* ..{props}*/ }
|
||||
{{
|
||||
todo!("this neesd to be implemented");
|
||||
let props = TallerProps {a: "hello"};
|
||||
rsx!(Taller {a: "a"})
|
||||
}}
|
||||
|
||||
// Can take children
|
||||
Taller { a: "asd", div {} }
|
||||
Taller { a: "asd", div {"hello world!"} }
|
||||
}
|
||||
})
|
||||
};
|
||||
|
@ -83,7 +179,8 @@ mod baller {
|
|||
use super::*;
|
||||
pub struct BallerProps {}
|
||||
|
||||
pub fn Baller(ctx: Context<()>) -> VNode {
|
||||
/// This component totally balls
|
||||
pub fn Baller(cx: Context<()>) -> VNode {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +190,7 @@ pub struct TallerProps {
|
|||
a: &'static str,
|
||||
}
|
||||
|
||||
/// This component is taller than most :)
|
||||
pub fn Taller(ctx: Context<TallerProps>) -> VNode {
|
||||
let b = true;
|
||||
todo!()
|
||||
|
|
|
@ -6,22 +6,26 @@
|
|||
//! Under the hood, the dioxus_webview crate bridges a native Dioxus VirtualDom with a custom prebuit application running
|
||||
//! in the webview runtime. Custom handlers are provided for the webview instance to consume patches and emit user events
|
||||
//! into the native VDom instance.
|
||||
//!
|
||||
//! Currently, NodeRefs won't work properly, but all other event functionality will.
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::webview::launch(|ctx| {
|
||||
let (count, set_count) = use_state(&ctx, || 0);
|
||||
|
||||
ctx.render(rsx! {
|
||||
div {
|
||||
h1 { "Dioxus Desktop Demo" }
|
||||
p { "Count is {count}" }
|
||||
button {
|
||||
"Click to increment"
|
||||
onclick: |_| set_count(count + 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
dioxus::webview::launch(App);
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx| {
|
||||
let (count, set_count) = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
h1 { "Dioxus Desktop Demo" }
|
||||
p { "Count is {count}" }
|
||||
button {
|
||||
"Click to increment"
|
||||
onclick: move |_| set_count(count + 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
|
|
@ -13,11 +13,12 @@ Sorted by priority
|
|||
| Context | ✅ | ✅ | share state through the tree |
|
||||
| Hook | ✅ | ✅ | memory cells in components |
|
||||
| SSR | ✅ | ✅ | render directly to string |
|
||||
| Runs natively | ✅ | 👀 | runs as a portable binary w/ extra tooling |
|
||||
| Runs natively | ✅ | 👀 | runs as a portable binary w/o a runtime (Node) |
|
||||
| Component Children | ✅ | ✅ | cx.children() as a list of nodes |
|
||||
| Null components | ✅ | ✅ | allow returning no components |
|
||||
| No-div components | ✅ | ✅ | components that render components |
|
||||
| Fragments | ✅ | ✅ | rsx! can return multiple elements without a root |
|
||||
| Manual Props | 👀 | ✅ | Manually pass in props |
|
||||
| NodeRef | 👀 | ✅ | gain direct access to nodes |
|
||||
| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs |
|
||||
| CSS/Inline Styles | 🛠 | ✅ | syntax for inline/conditional styles |
|
||||
|
|
|
@ -778,7 +778,7 @@ Any function prefixed with "use" should not be called conditionally.
|
|||
}
|
||||
|
||||
/// There are hooks going on here!
|
||||
fn use_context<T: 'static>(&self) -> &'src Rc<T> {
|
||||
fn use_context<T: 'static>(&self) -> &'src T {
|
||||
self.try_use_context().unwrap()
|
||||
}
|
||||
|
||||
|
|
|
@ -23,21 +23,15 @@ wasm-bindgen-test = "0.3.21"
|
|||
once_cell = "1.7.2"
|
||||
atoms = { path="../atoms" }
|
||||
|
||||
# wasm-bindgen = "0.2.70"
|
||||
# futures = "0.3.12"
|
||||
# html-validation = { path = "../html-validation", version = "0.1.1" }
|
||||
|
||||
async-channel = "1.6.1"
|
||||
nohash-hasher = "0.2.0"
|
||||
anyhow = "1.0.41"
|
||||
# futures-lite = "1.11.3"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.50"
|
||||
features = [
|
||||
"Comment",
|
||||
"Document",
|
||||
# "DataTransfer",
|
||||
"Element",
|
||||
"HtmlElement",
|
||||
"HtmlInputElement",
|
||||
|
@ -64,18 +58,12 @@ features = [
|
|||
"DocumentType",
|
||||
"CharacterData",
|
||||
"HtmlOptionElement",
|
||||
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = 's'
|
||||
|
||||
# debug = true
|
||||
|
||||
# [profile.release]
|
||||
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
|
@ -83,7 +71,3 @@ crate-type = ["cdylib", "rlib"]
|
|||
im-rc = "15.0.0"
|
||||
rand = { version="0.8.4", features=["small_rng"] }
|
||||
uuid = { version="0.8.2", features=["v4", "wasm-bindgen"] }
|
||||
|
||||
[[example]]
|
||||
name = "todomvc"
|
||||
path = "./examples/todomvc/main.rs"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//!
|
||||
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_web::WebsysRenderer;
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -231,6 +231,6 @@ pub mod atoms {}
|
|||
// #[cfg(feature = "desktop")]
|
||||
pub mod webview {
|
||||
//! A webview based renderer for building desktop applications with Dioxus
|
||||
use dioxus_core::prelude::FC;
|
||||
pub fn launch<P>(f: FC<P>) {}
|
||||
use dioxus_core::prelude::{Properties, FC};
|
||||
pub fn launch<P: Properties>(f: FC<P>) {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue