19个版本
0.2.13 | 2022年7月24日 |
---|---|
0.2.12 | 2022年5月26日 |
0.2.9 | 2022年4月28日 |
0.1.4 | 2022年4月7日 |
#285 in WebAssembly
每月49次下载
87KB
2.5K SLoC
livid
livid是一个轻量级的Rust前端crate,用于通过WebAssembly创建Web应用。它提供了以下优势
- 对web-sys的薄包装
- 无vdom。
- 无宏!
- 后端无关。
要求
- wasm32-unknown-unknown目标
rustuptarget add wasm32-unknown-unknown
用法
- 安装livid-cli crate(简化Web应用的构建和打包)
cargo安装livid-cli
- 您可以为CSS文件/URL添加链接,并使用Widget::set_class_name()来利用CSS样式。
- 创建项目
[dependencies]
livid = "0.2"
在您的Rust源文件中
use livid::{enums::*, prelude::*, *};
enum Action {
Increment(i32),
Decrement(i32),
}
fn btn(action: Action) -> button::Button {
let (label, color, step) = {
match action {
Action::Increment(v) => ("Increment", Color::Green, v),
Action::Decrement(v) => ("Decrement", Color::Red, -v),
}
};
let btn = button::Button::default().with_label(label);
btn.set_label_size(20);
btn.set_label_color(color);
btn.set_margin(10);
btn.set_padding(10);
btn.set_frame(FrameType::RFlatBox);
btn.add_callback(Event::Click, move |_| {
let frame = widget::Widget::from_id("result").unwrap();
let mut old: i32 = frame.text_content().unwrap().parse().unwrap();
old += step;
frame.set_text_content(Some(&old.to_string()));
});
btn
}
fn main() {
let col = group::Column::default_fill();
col.set_justify_content(AlignContent::Center);
btn(Action::Increment(1));
let f = frame::Frame::default().with_label("0").with_id("result");
f.set_padding(20);
f.set_label_size(20);
btn(Action::Decrement(1));
col.end();
}
- 使用livid-cli构建和提供服务
livid build
或livid serve
- 使用livid deploy构建具有wasm的前端桌面应用
livid deploy--宽度=600 --高度=400
低级API
Livid还有一个低级小部件API
use livid::{enums::*, prelude::*, *};
fn div() -> widget::Widget {
widget::Widget::new(WidgetType::Div)
}
fn btn(i: i32) -> widget::Widget {
let btn = widget::Widget::new(WidgetType::Button);
let (label, col) = if i > 0 {
("Increment", "Green")
} else {
("Decrement", "Red")
};
btn.set_text_content(Some(label));
btn.set_style(Style::Color, col);
btn.add_callback(Event::Click, move |_| {
let result = widget::Widget::from_id("result").unwrap();
let mut old: i32 = result.text_content().unwrap().parse().unwrap();
old += i;
result.set_text_content(Some(&old.to_string()));
});
btn
}
fn main() {
document::Document::get().set_title("Counter");
let btn_inc = btn(1);
let btn_dec = btn(-1);
let main_div = div();
main_div.append(&btn_inc);
main_div.append(&btn_dec);
let result = div();
result.set_id("result");
result.set_text_content(Some("0"));
result.set_style(Style::FontSize, "22px");
let btns = document::Document::get().get_elements_by_tag_name("BUTTON");
for btn in btns.iter() {
// set their fontSize to 22 pixesl
btn.set_style(Style::FontSize, "22px");
}
}
带有CSS的低级示例
use livid::{
document::Document,
enums::WidgetType::{self, *},
widget::Widget,
};
fn w(typ: WidgetType) -> Widget {
Widget::new(typ)
}
fn main() {
Document::get().set_title("Form");
Document::add_css_link("https://cdn.jsdelivr.net.cn/npm/[email protected]/css/bulma.min.css");
Document::add_css_link("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css");
let form = w(Form);
form.set_class_name("box");
form.append(&{
let div = w(Div);
div.set_class_name("field");
div.append(&{
let label = w(Label);
label.set_class_name("label");
label.set_inner_html(r#"<span class='fa fa-envelope'></span> Email"#);
label
});
div.append(&{
let div = w(Div);
div.set_class_name("control");
div.append(&{
let inp = w(Input);
inp.set_class_name("input");
inp.set_attribute("type", "email").unwrap();
inp.set_attribute("placeholder", "[email protected]").unwrap();
inp
});
div
});
div
});
}
高级API
Livid不强制使用。您可以在其之上构建高级抽象
mod detail; // we define an OnEvent trait for our buttons
use crate::detail::{OnEvent, App, Settings};
use livid::{enums::*, prelude::*, *};
#[derive(Default, Copy, Clone)]
struct Counter {
value: i32,
}
#[derive(Debug, Clone, Copy)]
enum Message {
IncrementPressed,
DecrementPressed,
}
impl App for Counter {
type Message = Message;
fn new() -> Self {
Self::default()
}
fn title(&self) -> String {
String::from("Counter - livid")
}
fn update(&mut self, message: Message) {
match message {
Message::IncrementPressed => {
self.value += 1;
}
Message::DecrementPressed => {
self.value -= 1;
}
}
}
fn view(&mut self) {
let col = group::Column::default_fill();
button::Button::default()
.with_label("Increment")
.on_trigger(Message::IncrementPressed);
frame::Frame::default().with_label(&self.value.to_string());
button::Button::default()
.with_label("Decrement")
.on_trigger(Message::DecrementPressed);
col.end();
}
}
fn main() {
Counter::new().run(Settings {
size: (300, 200),
win_color: Some(Color::Rgb(Rgb(250, 250, 250))),
..Default::default()
})
}
请参阅示例目录以获取更完整的示例。
依赖项
~6.5–8.5MB
~171K SLoC