A small and fast frontend framework for Single Page Application in Rust.
This project is in its early stage, things are still missing.
- Routing is just at the minimum level. You have to implement it manually.
- No support for SSR.
- No event delegation.
- No RSX.
- Spair uses Rust syntax to describe the HTML fragments, then uses Rust attribute-macros to transform them into spair's views or components. This is a kind of abusing Rust, and may become invalid by changes in Rust in the future.
- The library is still a WIP.
- No community.
- Both small and fast.
- This was correct for previous versions. The current version (the main branch) is a complete redesign. No benchmarks for the new design yet.
- No vDOM.
- Spair uses procedure macros to find the exact nodes that need to be updated at compile time. Then in updating, it just updates the nodes directly. Items in keyed-lists still need to be located by their keys before doing updates.
- Rust-like syntax
- Format by rustfmt.
- (But may become invalid by changes in Rust in the future)
- Routing (but just basic support).
- Plan to add: reactive-like update.
- Queue render (reactive-like, but not using any kind of signals), just queue relevant pieces of code to render changes on data change. (Old versions had this, but not available in new design in main branch yet. It is planned to be added back)
- Missing things here and there...
- Errr, this is definitely a why not, obviously. I just put this here to remind potential users not to surprise about missing things :D.
Prerequisites:
In an example folder:
trunk serve
or, if it's slow, use: (especialy examples/boids or examples/game_of_life)
trunk serve --release
Open your browser at http://localhost:8080
Not yet. /examples/* is the best place to start now.
Sections below provide first looks into Spair.
The following code create a new view name UpdownButton. It will never be updated.
#[create_view]
impl UpdownButton {
fn create(handler: CallbackArg<MouseEvent>, text: &str) {}
fn update() {}
fn view() {
button(on_click = handler, text(text))
}
}The following code will generate impl Component for AppState {...}. Values get from ucontext will be updated, values get from ccontext will never get updated.
struct AppState {
value: i32,
}
#[impl_component]
impl AppState {
fn create(ccontext: &Context<Self>) {}
fn update(ucontext: &Context<Self>) {}
fn view() {
div(
// mount this div at element with id="root" in the HTML document
replace_at_element_id = "root",
UpdownButton(ccontext.comp.callback_arg(|state, _| state.value -= 1), "-"),
ucontext.state.value,
UpdownButton(ccontext.comp.callback_arg(|state, _| state.value += 1), "+"),
)
}
}
// Start the app
fn main() {
spair::start_app(|_| AppState { value: 42 });
}HTML's tags and attributes are implemented as methods in Spair. Names that
are conflicted with Rust's keywords are implemented using raw identifers
such as r#type, r#for...