8个版本
0.1.7 | 2024年2月4日 |
---|---|
0.1.6 | 2024年2月4日 |
0.1.5 | 2024年1月9日 |
0.1.2 | 2023年12月27日 |
在 WebAssembly 中排名第212
22KB
176 代码行
一个示例项目,展示了如何在Rust中创建自定义组件。
v0.1.7
- Cargo.toml文件中的描述已纠正
- 文档链接已纠正
v0.1.6
- 删除了JS片段。现在没有JS片段,只有Rust 😀。
- 修复了文档
v0.1.5
- 添加了set_data函数。允许将状态传递到自定义元素。
- 添加了一个具有材质两行列表和状态的示例
v0.1.4
- 修复了attribute_changed回调函数的参数类型问题
- 添加了一个具有材质轮廓文本字段的示例
- 添加了具有默认实现的adopted_callback函数
v0.1.3
- 添加了add_template函数
- 添加了一个包含模板的示例
示例
基本示例
use rs_web_component::{define_element, Component};
use wasm_bindgen::prelude::*;
use web_sys::{HtmlElement, ShadowRoot, ShadowRootInit, ShadowRootMode};
pub enum ThisVal {
Value(HtmlElement),
None,
}
pub enum RootVal {
Value(ShadowRoot),
None,
}
struct MyComponent {
root: RootVal,
this: ThisVal,
}
impl Component for MyComponent {
fn init(&mut self, this: HtmlElement) {
self.this = ThisVal::Value(this);
}
fn observed_attributes(&self) -> Vec<String> {
return vec!["test".to_string()];
}
fn attribute_changed_callback(&self, _name: String, _old_value: String, _new_value: String) {
if _old_value != _new_value {
self.get_root().set_inner_html(self.render().as_str())
}
}
fn connected_callback(&mut self) {
self.root = RootVal::Value(
self.get_this()
.attach_shadow(&ShadowRootInit::new(ShadowRootMode::Open))
.unwrap(),
);
self.get_root().set_inner_html(self.render().as_str())
}
fn disconnected_callback(&self) {}
}
impl MyComponent {
fn render(&self) -> String {
"<div><span>Hello from Rust</span></div>".to_string()
}
fn get_root(&self) -> &ShadowRoot {
return match &self.root {
RootVal::Value(root) => &root,
RootVal::None => panic!("not a root!"),
};
}
fn get_this(&self) -> &HtmlElement {
match &self.this {
ThisVal::Value(val) => val,
ThisVal::None => panic!("not an HtmlElement"),
}
}
}
#[wasm_bindgen(start)]
fn run() {
define_element("test-component".to_string(), || -> Box<dyn Component> {
Box::new(MyComponent {
root: RootVal::None,
this: ThisVal::None,
})
});
}
带有事件处理器的示例
use rs_web_component::{define_element, Component};
use wasm_bindgen::prelude::*;
use web_sys::{
CustomEvent, CustomEventInit, Event, HtmlElement, ShadowRoot, ShadowRootInit, ShadowRootMode,
};
const BUTTON_EVENT_NAME: &str = "buttonClicked";
pub enum ThisVal {
Value(HtmlElement),
None,
}
pub enum RootVal {
Value(ShadowRoot),
None,
}
pub enum CallbackVal {
Value(Closure<dyn FnMut(Event) + 'static>),
None,
}
struct MyComponent {
root: RootVal,
this: ThisVal,
callback: CallbackVal,
}
impl Component for MyComponent {
fn init(&mut self, this: HtmlElement) {
self.this = ThisVal::Value(this);
}
fn observed_attributes(&self) -> Vec<String> {
return vec!["test".to_string()];
}
fn attribute_changed_callback(&self, _name: String, _old_value: String, _new_value: String) {}
fn connected_callback(&mut self) {
self.root = RootVal::Value(
self.get_this()
.attach_shadow(&ShadowRootInit::new(ShadowRootMode::Open))
.unwrap(),
);
self.get_root().set_inner_html(self.render().as_str());
self.attach_event_handler();
}
fn disconnected_callback(&self) {
self.detach_event_handler();
}
}
impl MyComponent {
fn render(&self) -> String {
"<div><button>Click me</button></div>".to_string()
}
fn attach_event_handler(&mut self) {
let btn = self.get_root().query_selector("button").unwrap().unwrap();
let closure = Closure::<dyn FnMut(Event) + 'static>::new(move |e: Event| {
let evt = CustomEvent::new_with_event_init_dict(
BUTTON_EVENT_NAME,
CustomEventInit::new().composed(true).bubbles(true),
)
.unwrap();
let _ = btn.dispatch_event(&evt);
});
self.callback = CallbackVal::Value(closure);
let btn = self.get_root().query_selector("button").unwrap().unwrap();
let _ = btn.add_event_listener_with_callback(
"click",
self.get_callback().as_ref().unchecked_ref(),
);
}
fn detach_event_handler(&self) {
let btn = self.get_this().query_selector("button").unwrap().unwrap();
let _ = btn.remove_event_listener_with_callback(
"click",
self.get_callback().as_ref().unchecked_ref(),
);
}
fn get_callback(&self) -> &Closure<dyn FnMut(Event) + 'static> {
return match &self.callback {
CallbackVal::Value(callback) => callback,
&CallbackVal::None => panic!("not a callback!"),
};
}
fn get_root(&self) -> &ShadowRoot {
return match &self.root {
RootVal::Value(root) => &root,
RootVal::None => panic!("not a root!"),
};
}
fn get_this(&self) -> &HtmlElement {
match &self.this {
ThisVal::Value(val) => val,
ThisVal::None => panic!("not an HtmlElement"),
}
}
}
#[wasm_bindgen(start)]
fn run() {
define_element("test-component".to_string(), || -> Box<dyn Component> {
Box::new(MyComponent {
root: RootVal::None,
this: ThisVal::None,
callback: CallbackVal::None,
})
});
}
依赖项
~6.5–8.5MB
~169K SLoC