2 个不稳定版本

0.2.0 2021年6月28日
0.1.0 2021年6月16日

#1887网页编程

每月 21 次下载

MIT 许可证

105KB
2.5K SLoC

Pinwheel

Pinwheel 是一个用于使用 Rust 编写网页用户界面的库。

示例

下面的示例在每次按下 <p> 时增加一个 <button> 的值。

let body = dom::window().unwrap().document().unwrap().body().unwrap().into();
let count = Mutable::new(0);
let on_click = {
  let count = count.clone();
  move |_| {
    count.replace_with(|count| *count + 1);
  }
};
let count_text = count.signal().map(|count| p().child(count.to_string()));
let increment_button = button().onclick(on_click).child("Increment");
let counter = div()
  .style(style::DISPLAY, "grid")
  .style(style::JUSTIFY_CONTENT, "start")
  .child_signal(count_text)
  .child(increment_button);
App::new(body, counter).forget();

特性

精细粒度反应性

Pinwheel 使用 futures-signals 包来更新随着应用状态变化而确切需要更新的 DOM 节点。无需虚拟 DOM!

同构渲染

当编译成浏览器版本时,Pinwheel 通过创建 DOM 节点进行渲染。在服务器上,它通过将 HTML 写入字符串进行渲染。

let root = p().child("Hello, World!");

// On the server...
assert_eq!(root.to_string(), "<p>Hello, World!</p>");

// On the client...
App::new(dom_node, root).forget();

部分激活

在服务器渲染后,在客户端使应用的一部分交互式。在下面的示例中,dynamic_component 将在服务器和客户端渲染,但 static_component 只会在服务器上渲染。

let root = p().child("Hello, World!");

// On the server...
let html = div()
  .child(static_component)
  .child(Dehydrate::new("hydration_id", dynamic_component))
  .to_string();

// On the client...
hydrate("hydration_id");

无宏构建器

Pinwheel 提供了无宏的 DOM 元素静态类型构建器,因此您将获得 rustfmt 格式化和 rust-analyzer 自动完成的全部好处。

let count_p = count.signal().map(|count| p().child(count.to_string()));
let increment_button = button().onclick(on_click).child("Increment");
let root = div()
  .style(style::DISPLAY, "grid")
  .style(style::JUSTIFY_CONTENT, "start")
  .child_signal(count_p)
  .child(increment_button);

组件

将应用组织成自包含的组件。

use pinwheel::prelude::*;

struct Alert {
  title: String,
  color: Option<String>,
  children: Vec<Node>,
}

impl Component for Alert {
  fn into_node(self) -> Node {
    div()
      .style(style::BACKGROUND_COLOR, self.color)
      .child(h1().child(self.title))
      .children(self.children)
      .into_node()
  }
}

组件构建器

组件通常有几个必需字段和许多可选字段。Pinwheel 提供了一个 derive 宏,使使用这些组件变得简单。

#[derive(ComponentBuilder)]
struct Alert {
  // required field
  title: String,
  // optional field
  #[optional]
  color: Option<String>,
  #[children]
  children: Vec<Node>,
}

现在,您可以使用构建器模式创建一个警报。

Alert::new("Alert!")
  .color("green".to_owned())
  .child("An alert occurred!")

依赖项

~12MB
~240K SLoC