gpt4 book ai didi

rust - 如何将特征绑定(bind)到使用 document.create_element 构建的元素

转载 作者:行者123 更新时间:2023-12-03 11:43:40 31 4
gpt4 key购买 nike

使用 Rust 和 wasm-bindgen 开发用于 Dom 操作的最小原型(prototype)/测试程序.

使用 document.create_element(tag) 构建元素,返回 web_sys::Element .元素被转换为特定类型,具体取决于标签,例如 web_sys::HtmlButtonElement .这可行,并且还放入了一个小包装器,用于设置元素类型特定的构建器。

struct ElemSpec<T> {
html_tag : html_const::HtmlTag<'static>,
resource_type: std::marker::PhantomData<T>
}

impl<T : wasm_bindgen::JsCast> ElemSpec<T> {

fn build_element(&self) -> T {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
let elem = document.create_element(&self.html_tag);

let elem = match elem {
Ok(e) => e,
Err(error) => {
panic!("Call to document.create_element failed with error: {:?}", error)
},
};
let result = wasm_bindgen::JsCast::dyn_into::<T>(elem);
let helement = match result {
Ok(e) => e,
Err(e) => {
panic!("Cast to specific Element failed tag:{}", &self.html_tag);
},
};
helement
}
}

const BUTTON_ELEM : ElemSpec<web_sys::HtmlButtonElement> =
ElemSpec{ html_tag: html_const::BUTTON, resource_type: std::marker::PhantomData};

这行得通, HtmlButtonElement内置:
let buttonElement = BUTTON_ELEM.build_element();
现在我寻找一个 trait Bound,它限制为元素,可以从 web_sys::Element 转换。 .例如。 HtmlSpanElement , HtmlDivElement , ..., HtmlButtonElement .

附加或替换绑定(bind)到 wasm_bindgen::JsCastimpl<T : wasm_bindgen::JsCast> ,这可以做到吗?

最佳答案

wasm_bindgen::JsCast::dyn_into 文档说明它依赖 JsCast::has_type , 进而调用 JsCast::instanceof .确实web_sys::Element确实实现了JsCast特征。其他 HTML 元素类型也是如此,例如 HtmlButtonElement .

该实现是从 Web IDL 生成的文件,它们是 Web 浏览器界面的正式定义。然而:

impl JsCast for Element {
fn instanceof(val: &JsValue) -> bool {
#[link(wasm_import_module = "__wbindgen_placeholder__")]
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
extern "C" {
fn __widl_instanceof_Element(val: u32) -> u32;
}
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
unsafe fn __widl_instanceof_Element(_: u32) -> u32 {
panic!("cannot check instanceof on non-wasm targets");
}
unsafe {
let idx = val.into_abi();
__widl_instanceof_Element(idx) != 0
}
}
}

生成的 instanceof方法调用到 WebIDL native 库。由于它跨越了语言边界,它不能告诉我们太多关于这些元素类型在 Rust 方面的共同点。

另一方面, HtmlButtonElement和其他人也实现 AsRef<Element> 作为:
impl AsRef<Element> for HtmlButtonElement {
#[inline]
fn as_ref(&self) -> &Element {
use wasm_bindgen::JsCast;
Element::unchecked_from_js_ref(self.as_ref())
}
}

所以你有它,其中一个常见的界限是 AsRef<Element> .这很可能是 web-sys 有意识的设计决定。作者,因为它对 WebIDL / JavaScript perspective 也有意义:

enter image description here

关于rust - 如何将特征绑定(bind)到使用 document.create_element 构建的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59692792/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com