#virtual-dom #front-end #wasm #web #javascript #rust

rust-fel

一个用于制作客户端单页应用的轻量级库

3 个版本

0.1.2 2020 年 10 月 18 日
0.1.1 2020 年 9 月 6 日
0.1.0 2020 年 8 月 30 日

11 in #virtual-dom

42 每月下载次数

MIT 许可证

51KB
593 代码行

rust-fel

Actions Status GitHub issues GitHub license Crates.io GitHub release (latest by date) Crates.io

一个依赖 rustwasm 的实验性前端库。

非常轻量级,不支持大部分 HTML 标准。还需要做更多工作,才能真正使其成为使用 rustwasm 创建客户端前端的有效选择。

一个工作示例可以在以下地址找到 rust-fel-example

功能

  • 状态管理
  • 类似 JSX 的语法
  • 从虚拟 DOM 构建文档对象模型。

使用

use crate::main_component::Main;
use wasm_bindgen::prelude::_;
extern crate rust_fel;

// invoked when the wasm module is instantiated
#[wasm_bindgen(start)]
pub fn main() -> Result<(), JsValue> {
  let main = Main::create();
  let app = rust_fel::App::new(main);
  app.mount("root");

  Ok(())
}

示例

Arust_fel struct 组件实现了 rust_fel::Component

use crate::action::Action;
use crate::handle;
use crate::main_child::{ChildProps, MainChild};
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug, Default, Clone)]
pub struct MainState {
  count: i32,
}

pub enum Actions {
  Counter(Action),
}

#[derive(Debug, Default, Clone)]
pub struct Main {
  child: handle::Handle<MainChild>,
  id: String,
  state: MainState,
  props: String,
}

impl Main {
  pub fn create() -> handle::Handle<Self> {
    let main = Main {
      id: "main".to_owned(),
      state: MainState {
      count: 0,
      },
      child: MainChild::create(),
      ..Default::default()
    };
    handle::Handle(Rc::new(RefCell::new(main)))
  }
}

impl rust_fel::Component for handle::Handle<Main> {
  type Properties = String;
  type Message = Actions;
  type State = MainState;

  fn add_props(&mut self, props: Self::Properties) {
    self.0.borrow_mut().props = props;
  }

  fn reduce_state(&mut self, message: Actions) {
    match message {
      Actions::Counter(Action::Increment) => self.0.borrow_mut().state.count += 100,
      Actions::Counter(Action::Decrement) => self.0.borrow_mut().state.count -= 100,
    }
    rust_fel::re_render(self.render(), Some(self.0.borrow().id.clone()));
  }

  fn render(&self) -> rust_fel::Element {
    let mut clone_for_props_closure = self.clone();
    let mut clone_for_inc = self.clone();
    let mut borrow = self.0.borrow_mut();
    let state = borrow.state.clone();
    let props_closure = Rc::new(RefCell::new(move || {
      clone_for_props_closure.reduce_state(Actions::Counter(Action::Decrement))
    }));

    let child_props = ChildProps {
      counter_props: state.count.to_string(),
      closure: Some(props_closure),
    };

    borrow.child.add_props(child_props);

    let main_text = rust_fel::html(format!(
      "<span | data-cy=main-text| >Main {}</span>",
      state.count.to_string()
      ));

    let inc_button = rust_fel::Element::new(
      "button".to_owned(),
      rust_fel::Props {
        text: Some("Increment".to_owned()),
        on_click: Some(Box::new(move || {
        clone_for_inc.reduce_state(Actions::Counter(Action::Increment))
        })),
        data_cy: Some("increment-main".to_owned()),
        children: Some(vec![inc_button_text]),
        ..Default::default()
        },
      );

    let main_el = rust_fel::Element::new(
      "div".to_owned(),
      rust_fel::Props {
        class_name: Some("main-el".to_owned()),
        children: Some(vec![main_text, inc_button, input_wrapper]),
        ..Default::default()
        },
      );

    let child_wrapper = rust_fel::Element::new(
      "div".to_owned(),
      rust_fel::Props {
        class_name: Some("child-wrapper".to_owned()),
        children: Some(vec![borrow.child.render()]),
        ..Default::default()
        },
      );

    rust_fel::Element::new(
      "div".to_owned(),
      rust_fel::Props {
        id: Some(borrow.id.clone()),
        class_name: Some("main".to_owned()),
        children: Some(vec![main_el, child_wrapper]),
        ..Default::default()
        },
      )
    }
}

一个使用 rust_fel::htmlrust_fel 函数组件。

  pub fn theme_switcher(on_click: rust_fel::ClosureProp, title: String) -> rust_fel::Element {
    let text = rust_fel::html(format!(
      "<span |class=theme-switcher-text|>{}</span>",
      title
  ));

  let theme_button = rust_fel::Element::new(
    "button".to_owned(),
    rust_fel::Props {
      on_click: Some(on_click),
      type_attr: Some("button".to_owned()),
      class_name: Some("theme-switcher-button".to_owned()),
      children: Some(vec![text]),
      data_cy: Some(title),
      ..Default::default()
      },
    );

  rust_fel::Element::new(
    "li".to_owned(),
    rust_fel::Props {
      children: Some(vec![theme_button]),
      ..Default::default()
      },
    )
}

依赖

~6.5–8.5MB
~170K SLoC