Perl日記

日々の知ったことのメモなどです。Perlは最近やってないです。

Rust と WebAssembly で ボタンを getElementById したり click 属性をつけたりするサンプルメモ

Rust の WebAssembly で、ボタンを押すと、div#msgdiv にテキストを入れて、window.alert() を実行するサンプルメモ。

trunk を使用している。

index.html
<!DOCTYPE html>
<html>

<head></head>

<body>
  <div id="msgdiv"></div>
  <input type="button" value="botan" id="foobtn">
</body>

</html>
Cargo.toml
[package]
name = "click-test"
version = "0.1.0"
edition = "2021"

# [lib]
# crate-type = ["cdylib", "rlib"]

[dependencies]
# log = "0.4.17"
# wasm-logger = "0.2.0"
# web-sys = "0.3.57"
wasm-bindgen = "0.2.80"

[dependencies.web-sys]
version = "0.3.57"
features = [
  'Window',
  'Document',
  'Element',
  'HtmlElement'
]
src/main.rs
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{Document, HtmlElement, Window};

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

fn window() -> Window {
    web_sys::window().unwrap()
}

fn document() -> Document {
    window().document().unwrap()
}

fn body() -> HtmlElement {
    document().body().unwrap()
}

pub fn main() {
    let cb = Closure::wrap(Box::new(move || {
        let el = document().get_element_by_id("msgdiv").unwrap();
        // テキストを入れる
        el.set_text_content(Some("Hello World"));
        // window.alert する
        alert("Hello, World");
    }) as Box<dyn Fn()>);

    let el = document().get_element_by_id("foobtn").unwrap();
    let el = el.dyn_ref::<HtmlElement>().unwrap();
    el.set_onclick(Some(cb.as_ref().unchecked_ref()));

    // これをしないと ブラウザコンソールで「Error: closure invoked recursively or destroyed already」と言って怒られる。
    // forget() しておくとメモリに残り続けるらしい。
    cb.forget();
}