This commit is contained in:
parent
0de7c0c27c
commit
4d96dd8987
1 changed files with 229 additions and 0 deletions
229
technology/dev/programming/frameworks/Dioxus.md
Normal file
229
technology/dev/programming/frameworks/Dioxus.md
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
---
|
||||||
|
obj: concept
|
||||||
|
website: https://dioxuslabs.com
|
||||||
|
repo: https://github.com/dioxuslabs/dioxus
|
||||||
|
---
|
||||||
|
|
||||||
|
# Dioxus
|
||||||
|
Dioxus is a modern, ergonomic, and high-performance Rust framework for building user interfaces using a Virtual DOM (like React). It supports Web, Desktop, TUI, and Mobile targets using a unified component model.
|
||||||
|
|
||||||
|
## Application
|
||||||
|
A dioxus app is just a normal rust application. To get started depend on `dioxus` and start with this `main.rs`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
dioxus::launch(App);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn App() -> Element {
|
||||||
|
rsx! {
|
||||||
|
p { "Hello World!" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Components (RSX)
|
||||||
|
|
||||||
|
Dioxus components are Rust functions that return `Element` and use the `rsx!` macro (similar to JSX). The UI is made with HTML and CSS.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn App() -> Element {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
h1 { "Hello, Dioxus!" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can define your own components and take values (Props):
|
||||||
|
|
||||||
|
```rust
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn MyComp(value: String, myevent: EventHandler<MouseEvent>, children: Element) -> Element {
|
||||||
|
rsx! {
|
||||||
|
button {
|
||||||
|
onclick: myevent,
|
||||||
|
title: value,
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
#[component]
|
||||||
|
fn App() -> Element {
|
||||||
|
rsx! {
|
||||||
|
MyComp {
|
||||||
|
// Event Handler
|
||||||
|
onclick: move |_| { println!("Clicked"); },
|
||||||
|
// Value
|
||||||
|
title: "my_title",
|
||||||
|
// children
|
||||||
|
p {
|
||||||
|
"Hello World"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Event Handler
|
||||||
|
|
||||||
|
Event handling is done inline using closures:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
rsx!(
|
||||||
|
button {
|
||||||
|
onclick: move |_| println!("Button clicked"),
|
||||||
|
"Click me"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Each event handler receives an event struct (e.g., `MouseEvent`, `FormEvent`).
|
||||||
|
|
||||||
|
## Hooks
|
||||||
|
|
||||||
|
Dioxus has a powerful hook system that allows you to manage state, side effects, and asynchronous operations in your components. With these hooks the UI gets automatically reloaded when needed.
|
||||||
|
|
||||||
|
> **Warning**: Always call the hooks in the same order or they will not work correctly. This means no hooks in loops or conditions.
|
||||||
|
|
||||||
|
### `use_signal`
|
||||||
|
|
||||||
|
Creates a reactive value that can be read and updated. When the value changes, the component re-renders.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let count = use_signal(|| 0);
|
||||||
|
rsx! {
|
||||||
|
button { onclick: move |_| count.set(count() + 1), "Increment" }
|
||||||
|
p { "Value is {count}" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `use_memo`
|
||||||
|
|
||||||
|
Computes a derived value that only re-evaluates when its dependencies change.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let doubled = use_memo(|| count() * 2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### `use_effect`
|
||||||
|
|
||||||
|
Runs a side effect after the component renders. Useful for operations which should run beside the UI.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use_effect(|| {
|
||||||
|
// Side effect code here
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `use_resource`
|
||||||
|
|
||||||
|
Manages an asynchronous resource, such as data fetched from an API.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let resource = use_resource(|| fetch_data());
|
||||||
|
```
|
||||||
|
|
||||||
|
### `use_drop`
|
||||||
|
|
||||||
|
Registers a callback to be run before the component is removed. Useful for cleaning up side effects.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use_drop(|| {
|
||||||
|
// Cleanup code here
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Assets
|
||||||
|
To include assets (like CSS) in our app, you can use the `asset!()` macro. This macro ensures the asset will be included in the final app bundle.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
static MY_CSS: Asset = asset!("/assets/main.css");
|
||||||
|
|
||||||
|
fn App() -> Element {
|
||||||
|
rsx! {
|
||||||
|
document::Stylesheet { href: MY_CSS }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Routing
|
||||||
|
|
||||||
|
You can have different routes in your app using dioxus router. To use the router enable the `router` feature in the `dioxus` crate.
|
||||||
|
|
||||||
|
**Define the routes**:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// All of our routes will be a variant of this Route enum
|
||||||
|
#[derive(Routable, PartialEq, Clone)]
|
||||||
|
enum Route {
|
||||||
|
// if the current location is "/home", render the Home component
|
||||||
|
#[route("/home")]
|
||||||
|
Home {},
|
||||||
|
// if the current location is "/blog", render the Blog component
|
||||||
|
#[route("/blog")]
|
||||||
|
Blog {},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Home() -> Element {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Blog() -> Element {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To use the router and actually render the routes, add it to your main App component:
|
||||||
|
```rust
|
||||||
|
fn App() -> Element {
|
||||||
|
rsx! {
|
||||||
|
document::Stylesheet { href: asset!("/assets/main.css") }
|
||||||
|
|
||||||
|
// Renders the current route
|
||||||
|
Router::<Route> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To move between routes you can either use a `Link` element or the `navigator`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Link Element
|
||||||
|
rsx! {
|
||||||
|
Link { to: Route::Home {}, "Go home!" }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigator
|
||||||
|
rsx! {
|
||||||
|
button {
|
||||||
|
onclick: move |_| {
|
||||||
|
let nav = navigator();
|
||||||
|
|
||||||
|
// push
|
||||||
|
nav.push(Route::Blog {});
|
||||||
|
|
||||||
|
// replace
|
||||||
|
nav.replace(Route::Home {});
|
||||||
|
|
||||||
|
// go back
|
||||||
|
nav.go_back();
|
||||||
|
|
||||||
|
// go forward
|
||||||
|
nav.go_forward();
|
||||||
|
},
|
||||||
|
"Go somewhere"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
Loading…
Add table
Add a link
Reference in a new issue