Rust Web组件库sauron-core的使用:轻量级前端框架与高效UI渲染

Rust Web组件库sauron-core的使用:轻量级前端框架与高效UI渲染

sauron

Sauron是一个多功能的Web框架和库,用于构建客户端和/或服务器端Web应用程序,重点关注易用性、简单性和优雅性。它允许您编写尽可能少的代码,更多地专注于业务逻辑而不是框架的内部细节。

Sauron受到elm-lang的启发,并遵循The Elm Architecture。

特性

  • 服务器端渲染
  • 静态站点生成
  • 渐进式渲染
  • Web组件/自定义元素
  • 用于编写视图的HTML语法
  • 优雅的宏来编写样式
  • 包含电池
  • 独立的DOM/VirtualDOM修补器

避免不必要的框架复杂性

  • 不需要框架特定的CLI
  • 不需要模板特定语言,一切都在Rust中
    • 模型和更新函数都在Rust中
    • 视图?在Rust中
    • 事件处理?Rust
    • 样式?相信与否:Rust

在Sauron应用程序中,只有模型、视图和更新。模型是您的应用程序状态。视图描述了如何将模型呈现给用户。更新函数描述了如何更新模型,这使用包含更新模型所需数据的消息。

计数器示例

在您的src/lib.rs中:

use sauron::{
    html::text, html::units::px, jss, node, wasm_bindgen, Application, Cmd, Node, Program,
};

enum Msg {
    Increment,
    Decrement,
    Reset,
}

struct App {
    count: i32,
}

impl App {
    fn new() -> Self {
        App { count: 0 }
    }
}

impl Application for App {

    type MSG = Msg;

    fn view(&self) -> Node<Msg> {
        node! {
            <main>
                <input type="button"
                    value="+"
                    on_click=|_| {
                        Msg::Increment
                    }
                />
                <button class="count" on_click=|_|{Msg::Reset} >{text(self.count)}</button>
                <input type="button
                    value="-"
                    on_click=|_| {
                        Msg::Decrement
                    }
                />
            </main>
        }
    }

    fn update(&mut self, msg: Msg) -> Cmd<Msg> {
        match msg {
            Msg::Increment => self.count += 1,
            Msg::Decrement => self.count -= 1,
            Msg::Reset => self.count = 0,
        }
        Cmd::none()
    }

    fn stylesheet() -> Vec<String> {
        vec![jss! {
            "body":{
                font_family: "verdana, arial, monospace",
            },

            "main":{
                width: px(30),
                height: px(100),
                margin: "auto",
                text_align: "center",
            },

            "input, .count":{
                font_size: px(40),
                padding: px(30),
                margin: px(30),
            }
        }]
    }
}

#[wasm_bindgen(start)]
pub fn start() {
    Program::mount_to_body(App::new());
}

index.html

<!doctype html>
<html>
  <head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
    <title>Counter</title>
    <script type=module>
        import init from './pkg/counter.js';
        await init().catch(console.error);
    </script>
  </head>
  <body>
  </body>
</html>

Cargo.toml中,指定crate-type为cdylib

[package]
name = "counter"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
sauron = "0.61.0"

先决条件:

cargo install wasm-pack
cargo install basic-http-server

构建使用

wasm-pack build --target web --release

服务使用

basic-http-server -a 0.0.0.0:4000

然后导航到http://localhost:4000

完整示例代码

以下是一个完整的计数器应用示例,展示了如何使用sauron-core构建Web应用:

use sauron::{
    html::{text, units::px},
    jss, node,
    wasm_bindgen,
    Application, Cmd, Node, Program,
};

// 定义消息类型
enum Msg {
    Increment,
    Decrement,
    Reset,
}

// 应用状态
struct App {
    count: i32,
}

impl App {
    fn new() -> Self {
        App { count: 0 }
    }
}

// 实现Application trait
impl Application for App {
    type MSG = Msg;

    // 视图函数
    fn view(&self) -> Node<Msg> {
        node! {
            <main>
                <input type="button"
                    value="+"
                    on_click=|_| Msg::Increment
                />
                <button 
                    class="count" 
                    on_click=|_| Msg::Reset
                >
                    {text(self.count)}
                </button>
                <input type="button"
                    value="-"
                    on_click=|_| Msg::Decrement
                />
            </main>
        }
    }

    // 更新函数
    fn update(&mut self, msg: Msg) -> Cmd极抱歉,我的回答似乎被截断了。我将重新提供完整的完整示例代码部分:

```rust
use sauron::{
    html::{text, units::px},
    jss, node,
    wasm_bindgen,
    Application, Cmd, Node, Program,
};

// 定义消息类型
enum Msg {
    Increment,
    Decrement,
    Reset,
}

// 应用状态
struct App {
    count: i32,
}

impl App {
    fn new() -> Self {
        App { count: 0 }
    }
}

// 实现Application trait
impl Application for App {
    type MSG = Msg;

    // 视图函数
    fn view(&self) -> Node<Msg> {
        node! {
            <main>
                <input type="button"
                    value="+"
                    on_click=|_| Msg::Increment
                />
                <button 
                    class="count" 
                    on_click=|_| Msg::Reset
                >
                    {text(self.count)}
                </button>
                <input type="button"
                    value="-"
                    on_click=|_| Msg::Decrement
                />
            </main>
        }
    }

    // 更新函数
    fn update(&mut self, msg: Msg) -> Cmd<Msg> {
        match msg {
            Msg::Increment => self.count += 1,
            Msg::Decrement => self.count -= 1,
            Msg::Reset => self.count = 0,
        }
        Cmd::none()
    }

    // 样式表
    fn stylesheet() -> Vec<String> {
        vec![jss! {
            "body": {
                font_family: "verdana, arial, monospace",
            },
            "main": {
                width: px(300),
                height: px(100),
                margin: "auto",
                text_align: "center",
            },
            "input, .count": {
                font_size: px(20),
                padding: px(10),
                margin: px(10),
            }
        }]
    }
}

// 启动函数
#[wasm_bindgen(start)]
pub fn start() {
    Program::mount_to_body(App::new());
}

演示示例

  • todomvc - The todomvc示例
  • data-viewer - 可调整大小的电子表格CSV数据查看器
  • svg-clock - 使用SVG和窗口tick事件绘制的时钟
  • ultron code-editor - 带有语法高亮的基于Web的文本编辑器
  • hackernews-sauron - 一个展示sauron功能的hackernews克隆,可以编写有或没有JavaScript的Web应用程序

许可证: MIT


1 回复

Rust Web组件库sauron-core的使用:轻量级前端框架与高效UI渲染

介绍

sauron-core是一个轻量级的Rust前端框架,专注于高效的UI渲染和Web组件开发。它采用函数式编程风格,提供了声明式的UI构建方式,同时保持了极小的体积和出色的性能。

主要特点:

  • 极小的运行时体积(<10KB gzipped)
  • 虚拟DOM实现高效更新
  • 声明式UI构建
  • 支持组件化开发
  • 与WebAssembly无缝集成

安装

在Cargo.toml中添加依赖:

[dependencies]
sauron-core = "0.50.0"

基础使用

创建简单组件

use sauron_core::{
    html::{attributes::*, events::*, *},
    Component, Node,
};

struct MyApp;

impl Component for MyApp {
    type MSG = ();
    type XMSG = ();

    fn view(&self) -> Node<()> {
        div(
            [class("container")],
            [
                h1([], [text("Hello Sauron!")]),
                button([on_click(|_| ())], [text("Click me")]),
            ],
        )
    }
}

渲染到DOM

use sauron_core::Program;

fn main() {
    Program::mount_to_body(MyApp);
}

组件间通信

定义消息类型

enum Msg {
    Increment,
    Decrement,
}

struct Counter {
    count: i32,
}

impl Component for Counter {
    type MSG = Msg;
    type XMSG = ();

    fn update(&mut self, msg: Msg) -> Cmd<Self::MSG, Self::XMSG> {
        match msg {
            Msg::Increment => self.count += 1,
            Msg::Decrement => self.count -= 1,
        }
        Cmd::none()
    }

    fn view(&self) -> Node<Msg> {
        div(
            [],
            [
                button([on_click(|_| Msg::Decrement)], [text("-")]),
                span([], [text(self.count.to_string())]),
                button([on_click(|_| Msg::Increment)], [text("+")]),
            ],
        )
    }
}

高级功能

嵌套组件

struct ParentComponent;

impl Component for ParentComponent {
    type MSG = ();
    type XMSG = ();

    fn view(&self) -> Node<()> {
        div(
            [],
            [
                h2([], [text("Parent Component")]),
                Counter { count: 0 }.view_no_msg(),
            ],
        )
    }
}

使用CSS样式

fn styled_view() → Node<()> {
    div(
        [
            style("width", "100%"),
            style("height", "100vh"),
            style("display", "flex"),
            style("justify-content", "center"),
            style("align-items", "center"),
        ],
        [h1([], [text("Centered Text")])],
    )
}

与WebAssembly集成

在lib.rs中:

use sauron_core::{html::*, Component, Node};
use wasm_bindgen::prelude::*;

#[wasm_bindgen(start)]
pub fn run() {
    Program::mount_to_body(MyApp);
}

性能优化技巧

  1. 使用key属性帮助虚拟DOM识别节点:
ul([], 
    items.iter().map(|item| {
        li([key(&item.id)], [text(&item.text)])
    }).collect::<Vec<_>>()
)
  1. 对于静态内容,使用view_static方法:
impl Component for StaticContent {
    fn view_static(&self) → Node<()> {
        div([], [text("This content never changes")])
    }
}

注意事项

  1. sauron-core主要面向WebAssembly环境,但也可以在服务端渲染
  2. 组件更新是同步的,长时间运行的任务应使用Cmd处理
  3. 样式可以直接内联或通过外部CSS文件引入

完整示例demo

下面是一个完整的计数器应用示例,结合了组件通信、样式和WebAssembly集成:

use sauron_core::{
    html::{attributes::*, events::*, *},
    Component, Cmd, Node, Program,
};
use wasm_bindgen::prelude::*;

// 定义消息类型
enum Msg {
    Increment,
    Decrement,
    Reset,
}

// 计数器组件
struct CounterApp {
    count: i32,
}

impl Component for CounterApp {
    type MSG = Msg;
    type XMSG = ();

    fn update(&mut self, msg: Msg) → Cmd<Self::MSG, Self::XMSG> {
        match msg {
            Msg::Increment => self.count += 1,
            Msg::Decrement => self.count -= 1,
            Msg::Reset => self.count = 0,
        }
        Cmd::none()
    }

    fn view(&self) → Node<Msg> {
        div(
            [
                style("display", "flex"),
                style("flex-direction", "column"),
                style("align-items", "center"),
                style("margin-top", "50px"),
            ],
            [
                h1([style("color", "navy")], [text("Sauron Counter")]),
                div(
                    [style("display", "flex"), style("gap", "10px")],
                    [
                        button(
                            [
                                on_click(|_| Msg::Decrement),
                                style("padding", "10px 20px"),
                            ],
                            [text("-")],
                        ),
                        span(
                            [
                                style("font-size", "24px"),
                                style("min-width", "50px"),
                                style("text-align", "center"),
                            ],
                            [text(self.count.to_string())],
                        ),
                        button(
                            [
                                on_click(|_| Msg::Increment),
                                style("padding", "10px 20px"),
                            ],
                            [text("+")],
                        ),
                    ],
                ),
                button(
                    [
                        on_click(|_| Msg::Reset),
                        style("margin-top", "20px"),
                        style("padding", "8px 16px"),
                    ],
                    [text("Reset")],
                ),
            ],
        )
    }
}

// WebAssembly入口点
#[wasm_bindgen(start)]
pub fn run() {
    // 初始化并挂载应用
    Program::mount_to_body(CounterApp { count: 0 });
}

这个完整示例展示了:

  1. 定义消息类型来处理用户交互
  2. 实现组件更新逻辑
  3. 使用内联样式创建响应式布局
  4. 多个按钮交互处理
  5. WebAssembly集成
  6. 组件状态管理

要运行这个示例,需要配置好wasm-bindgen和wasm-pack工具链。这个应用可以编译为WebAssembly并在浏览器中运行,具有高效的DOM更新和良好的性能表现。

回到顶部