在 JavaScript 控制台中,我可以执行以下命令来创建
<input>
元素并演示它具有 click
方法。
let input = document.createElement("input");
input.type = "file";
console.log(input.click);
// ƒ click() { [native code] }
如果我尝试在编译为
wasm
的 Rust 中执行以下操作,则会收到错误:
let document: Document = Document::new().unwrap();
let input: Element = document.create_element("input").unwrap();
input.set_attribute("type", "file").unwrap();
# For debugging purposes, save a reference to a global variable so I can inspect it from the JavaScript console
let input_jsval : JsValue = input.clone().into();
js_sys::Reflect::set(&js_sys::global(), &JsValue::from_str("debug_input"), &input_jsval).unwrap();
# Attempt to click it
let input_html_element: HtmlElement = input_jsval.clone().into();
input_html_element.click();
当我运行
wasm
测试时,它会产生:
failures:
---- wasm_tests::tests::input_test output ----
log output:
error output:
wasm-bindgen: imported JS function that was not marked as `catch` threw an error: getObject(...).click is not a function
Stack:
TypeError: getObject(...).click is not a function
at http://127.0.0.1:8000/wasm-bindgen-test:589:25
如果我检查 JavaScript 控制台,我可以看到我保存的引用上没有
click
方法。
debug_input.click
// undefined
那么,为什么当我通过 JavaScript 创建
<input>
时,它会得到一个 click
方法,但如果我通过 wasm
做本质上相同的事情,它却不会呢?我怀疑通过 Element
从 HtmlElement
到 JsValue
的转换是有损的?有没有更直接的转换方式?
Q1: 有没有更直接的将
Element
转换为HtmlElement
?
A1:是的,如果您知道它确实是
HtmlElement
,那么您就可以let input_html_element: HtmlElement = input.dyn_into().unwrap();
。但是,如果输入实际上不是 HtmlElement
,则此操作将会失败,而本例则不是。
Q2:为什么不是
HtmlElement
?
A2:MDN 表示
Document::createElement
将返回“[a] 新的 HTMLElement
...如果文档是 HTMLDocument
,这是最常见的情况。否则将返回新的 Element
。 Document::new()
API 不会获取对当前窗口 document
的引用,而是创建一个新的(非 HTML)文档。相反,请使用:
let document: Document = web_sys::window().unwrap().document().unwrap();