9 个不稳定版本 (3 个破坏性更新)
0.3.2 | 2024 年 6 月 2 日 |
---|---|
0.3.1 | 2024 年 6 月 1 日 |
0.3.0 | 2024 年 5 月 31 日 |
0.2.2 | 2024 年 5 月 25 日 |
0.0.4 | 2024 年 5 月 12 日 |
#1056 在 WebAssembly
每月 107 次下载
在 dioxus-web-component 中使用
49KB
1K SLoC
dioxus-web-component-macro
提供一个处理宏来构建 Dioxus 网络组件。
示例
该宏替换了 Dioxus 的 #[component]
宏。
use dioxus::prelude::*;
use dioxus_web_component::{web_component, DioxusWebComponent};
use wasm_bindgen::prelude::*;
#[web_component]
fn MyWebComponent(
attr: Option<String>,
event: EventHandler<i64>,
) -> Element {
rsx ! {
div {
// ...
}
}
}
#[wasm_bindgen(main)]
pub fn main() {
// Register the web component (aka custom element)
register_my_web_component();
}
<!-- include the script generated with wasm-pack -->
<script type="module" src="my-web-component.js"></script>
<!-- in the body -->
<my-web-component attr="plop"></my-web-component>
使用方法
标签
自定义元素标签由组件名称构建。
默认情况下,标签是名称的短横线版本。例如,MyWebComponent
变为 my-web-component
。
您可以使用 tag
属性更改默认行为。
use dioxus::prelude::*;
use dioxus_web_component::{web_component, DioxusWebComponent};
#[web_component(tag = "plop-component")]
fn MyWebComponent(
// ...
) -> Element { todo!() }
<!-- in the body -->
<plop-component></plop-component>
ℹ️ 信息:自定义元素标签名称有约束。宏会为您检查标签的有效性。请参阅 MDN - 有效的自定义元素名称
样式
您可以使用 style
属性提供网络组件样式。
use dioxus::prelude::*;
use dioxus_web_component::{web_component, InjectedStyle};
#[web_component(
tag = "plop-greeting",
style = InjectedStyle::css(include_str!("./style.css"))
)]
fn Greeting(
// ...
) -> Element {
todo!()
}
dioxus_web_component::InjectedStyle
可以是包含在 HTML <style>...</style>
元素中的原始 CSS,或指向外部样式表的链接,或 InjectedStyle
样式的列表。
⚠️ 警告:网络组件被包装在一个带有 dioxus
CSS 类的 HTML div
中。
组件参数
您的组件的每个参数都应该是一个属性、一个属性或一个事件。请注意,参数可以是属性和属性的组合。
处理宏试图通过查看其类型来检测参数的类型。如果类型以 EventHandler
开头,则它被期望是一个事件。但是,这种检测并不可靠,因此您可能需要添加一个注释来纠正此行为。
如果需要自定义行为,也需要这些注释。
属性
属性类似于 href
HTML 元素。
您可以使用#[attribute]
注解将参数强制转换为属性。
当属性值发生变化时,dioxus组件将被渲染。
属性的HTML值是一个String
,因此您应该能够将该字符串解析为目标类型。
属性name
属性名默认是参数名的短横线命名法。您可以使用#[attribute(name = "my-custom-name")]
选择另一个名称。
属性option
属性可以是可选的或不选的。宏尝试通过类型名称自动检测它。但是检测并不可靠,所以如果需要,您可以使用#[attribute(option = true)]
来修复检测。
属性initial
属性需要有一个初始值。如果没有提供HTML属性或属性被删除时,将使用此值。
默认情况下,我们期望属性类型实现std::default::Default
。如果不是这种情况,或者您想为属性使用其他值,您可以使用#[attribute(initial = String::from("World"))]
提供您的默认表达式。
请注意,即使T
没有实现自己的Default
,Option<T>
也会使用Default
的None
值。
属性parse
HTML属性是字符串和可选的,因此我们需要将属性值转换为组件参数类型。
宏使用std::str::parse
方法。这意味着目标类型需要实现std::str::FromStr
特性。
在发生错误的情况下,使用初始值(见下文)。
如果您想更改此行为,可以提供您的解析表达式。
如果参数类型是可选的,此代码中使用解析表达式:let value = new_value.and_then(#parse);
. 如果类型不是可选的,代码如下:let value = new_value.and_then(#parse).unwrap_or_else(|| #initial);
.
解析表达式的预期类型是 FnOnce(String) -> Option<T>
. 默认表达式是 |value| value.parse().ok()
.
例如,如果你有一个类型为 bool
的参数 required
,并且你希望无论属性的任何内容,如果属性存在,值都为 true
,你可以使用 #[attribute(parse = |s| !s.is_empty() )]
.
属性
在Rust代码的Rust端,属性像属性一样工作。属性不能通过纯HTML访问,你需要JavaScript来获取/设置属性。
除了 String
表示形式,你需要能够将Rust类型转换为JavaScript类型(这里是一个 wasm_bindgen::JsValue
)。对于设置器,你需要进行相反的转换。
属性name
默认情况下,属性名是参数名的camelCase形式。你可以使用 #[property(name = "valueAsDate")]
选择另一个名称。
属性 readonly
如果设置为 true
,它将避免从JavaScript端设置属性。默认情况下会生成获取器和设置器。
属性initial
属性需要有一个初始值。此值在组件初始化时使用。
默认情况下,我们期望属性类型实现 std::default::Default
。如果不是这种情况,或者您想为您的属性使用另一个值,您可以使用以下代码提供默认表达式:#[property(initial = String::from("World"))]
.
属性 try_into_js
对于获取器,属性值应转换为 wasm_bindgen::JsValue
。默认情况下,我们使用 std::convert::TryInto
实现方式。
注意,有多种方式来实现 TryInto<JsValue>
,例如使用 impl TryFrom<T> for JsValue
或甚至 impl From<T> for JsValue
。请参阅 Rust TryInto
。
您可以使用 try_into_js
属性提供您的自定义转换到 JsValue
。解析表达式的预期类型是 FnOnce(T) -> Result<JsValue, _>
。注意,我们并不关心错误类型,因为错误情况被忽略,并返回 undefined
。
默认表达式是 |value| value.try_into()
。
将自定义类型(包装了 bool
)转换为示例
// ...
#[property(
try_into_js = |prop| {
let js_value = if prop.0 {
JsValue::TRUE
} else {
JsValue::FALSE
};
Ok::<_, Infallible>(js_value)
},
)]
prop2: MyProp,
// ...
#[derive(Clone, PartialEq, Default)]
struct MyProp(bool);
但在那种情况下,建议的方式是实现 From<MyProp> for JsValue
。
属性 try_from_js
对于设置器,属性值应从 wasm_bindgen::JsValue
转换。默认情况下,我们使用 std::convert::TryInto
实现方式。
请注意,实现TryInto<T>
有许多方法,例如使用impl TryFrom<JsValue> for T
或甚至impl From<JsValue> for T
。参见Rust TryInto
。
您可以使用try_from_js
属性提供您的自定义从JsValue
的转换。解析表达式的期望类型是FnOnce(JsValue) -> Result<T, _>
。请注意,我们不关心错误类型,因为错误情况被忽略。
默认表达式是 |value| value.try_into()
。
将自定义类型(包装了 bool
)转换为示例
// ...
#[property(
try_from_js= |value| Ok::<_, Infallible>(MyProp(value.is_truthy())),
)]
prop2: MyProp,
// ...
#[derive(Clone, PartialEq, Default)]
struct MyProp(bool);
但在那种情况下,推荐的方式是实现From<JsValue> for MyProp
。
事件
Web组件可以发送自定义事件。如果组件参数的类型是EventHandler
,则参数被检测为事件。由于这种检测并不可靠,您可以使用#[event]
注解强制参数为事件。
自定义事件细节对应于Dioxus EventHandler
的泛型类型。
⚠️ 重要:事件类型需要实现Into<JsValue>
并且是'static
(不包含任何引用)。
您可能需要手动实现它。您可以使用serde-wasm-bindgen
、gloo_utils::format::JsValueSerdeExt
、wasm_bindgen::UnwrapThrowExt
来实现Into<JsValue>
特质。
事件 name
HTML事件名称通过删除on_
(或on
)前缀并将名称转换为短横线命名法从参数名称检测得到。您可以通过name
属性选择您的值,例如使用#[event]]
来派发一个build
事件。
事件 no_bubble
默认情况下,事件会冒泡到DOM中。您可以使用以下代码避免冒泡:#[event(no_bubble = true)]
。
事件 no_cancel
默认情况下,事件是可取消的。您可以使用以下代码避免冒泡:#[event(no_cancel = true)]
。
依赖关系
~0.6–1.1MB
~25K SLoC