0x00 开篇
通过文章 Rust 与 Wasm
我们基本了解了 JavaScript 是如何调用 Rust 的函数,那本篇文章将带你了解使用 Rust 来调用 JavaScript 函数以及操作 Dom。
0x01 调用 JavaScript 函数
由于 Rust 是一门静态语言,所以在 Rust 中调用的 JavaScript 函数时必须声明。声明的方法如下:
#[wasm_bindgen] extern "C" { // js 函数 pub fn demo() }
假如我们声明一个 alert
函数,示例代码如下:
use wasm_bindgen::prelude::*; #[wasm_bindgen] extern { // js 函数 fn alert(msg: &str); } #[wasm_bindgen] pub fn alert_by_rust(msg: &str) { return alert(msg); }
所以,只要我们能够正确的声明 JavaScript 的函数,我们可以调用任意的 JavaScript 函数。
0x03 使用 web_sys 调用 JavaScript 函数
看了上面的方法,不知道大家有没有发现缺点。JavaScript 的函数太多了,我们该如何正确声明 JavaScript 的函数呢?即使我们正确声明了,后期维护起来可能也会很难。所以我们可以借助这两个 crate —— js-sys
和 web-sys
。这个库已经帮我们都声明好了,拿来用即可。
js-sys
:包含 ECMAScript 标准的全局范围一些变量和方法,不包括 Html节点操作,Web接口等其它环境的API。web-sys
:基于js-sys
并提供在浏览器内的接口,包括Web、Html节点操作等。
所以,在浏览器里上面两个 crate 要一起导入。先演示下用法:
use js_sys::Function; use wasm_bindgen::prelude::*; use web_sys::window; /// 调用 setTimeout #[wasm_bindgen] pub fn test_setTimeout() { // 声明一个函数 let func = Function::new_no_args(r#"alert("hello wasm")"#); // 获取 window let window = window().unwrap(); // window 调用setimeout window.set_timeout_with_callback_and_timeout_and_arguments_0(&func, 1000); }
注:由于 web-sys
存在多个 feature ,所以要参照文档,用到哪个类或者函数,就要声明哪个 feature。
上面的代码我就不演示了,有没有突然感觉到变得容易了起来。其实我们可以看下 js-sys
的源码,确实是给我们已经声明好了,已经省去了我们很多开发时间了。
0x04 使用 web_sys 操作 Dom
我们继续来感受下 web_sys
的强大吧,使用 web_sys
操作 Dom 同我们使用 JavaScript 大同小异,直接上代码:
/// 操作Dom #[wasm_bindgen] pub fn dom() { // 获取window let window = window().unwrap(); // 获取document let doc = window.document().unwrap(); // 获取test节点(我在html声明了一个div) let test_node = doc.get_element_by_id("test").unwrap(); // 在节点里添加内容 test_node.set_text_content(Some("Rust 操作 Dom")); // 最后再来个alert window.alert_with_message("我是通过 web_sys 生成的"); }
注:上面的代码用到的 feature 有 Window
, Document
, Element
, Node
。所以要在 .toml
文件里需要声明。
web-sys = { version = "0.3.60", features = ["Window", "Document", "Element", "Node"] }
Html 代码也贴一下吧:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Rust Wasm 测试</title> </head> <script type="module"> import init, {alert_by_rust, dom, test_setTimeout} from "./pkg/rust_wasm_dom.js"; init().then(() => { // alert_by_rust("hello world!") dom() }); </script> <body> <!-- 声明的div节点 --> <div id="test"></div> </body> </html>
编译直接看效果。
0x05 小结
看完文章了,有没有感觉到很简单。其实本篇文章的内容也比较少,关键是掌握 js-sys
和 web-sys
这两个 crate。可以说如果你学会了 Rust,那么你又掌握了一门可以写 wasm 的语言,而且可能写起来变得更加容易。说到这里可能有读者会考虑到,如果这个 web 端我全部使用 Rust 构建的 wasm 来写,是不是就不需要 JavaScript 了。其实上一篇文章我也提到过,感兴趣的读者可以研究下 Yew
这个框架。
最后说句题外话吧,近几年我发现前端的技术是更新最快的,每几个月就会出现新的前端框架,感觉每个语言都想取代 JavaScript,取代前端,我可以说前端是最卷的IT职业,没有之一。哎,心疼各位前端开发工程师们了。