使用 `char` 类型
`#[wasm_bindgen]` 宏将 rust `char` 类型转换为单个代码点的 js `string`,本示例展示了如何使用它。
打开本示例应该会显示一个带有随机字符作为其 `key` 和 0 作为其 `count` 的计数器。您可以点击 `+` 按钮增加计数器的计数。通过点击“添加计数器”按钮,您应该会看到一个新的计数器被添加到列表中,它使用不同的随机字符作为其 `key`。
在幕后,javascript 从一个字符数组中选择一个随机字符,并将其传递给 rust Counter 结构的构造函数,因此您在页面上看到的字符已经从 js 到 rust,再从 rust 回到 js 完成了完整的往返过程。
src/lib.rs
#![allow(unused)] fn main() { use wasm_bindgen::prelude::*; // lifted from the `console_log` example #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] fn log(s: &str); } #[wasm_bindgen] #[derive(Debug)] pub struct Counter { key: char, count: i32, } #[wasm_bindgen] impl Counter { pub fn new(key: char, count: i32) -> Counter { log(&format!("Counter::new({}, {})", key, count)); Counter { key, count } } pub fn key(&self) -> char { log("Counter.key()"); self.key } pub fn count(&self) -> i32 { log("Counter.count"); self.count } pub fn increment(&mut self) { log("Counter.increment"); self.count += 1; } pub fn update_key(&mut self, key: char) { self.key = key; } } }
index.js
/* eslint-disable no-unused-vars */
import { chars } from './chars-list.js';
let imp = import('./pkg');
let mod;
let counters = [];
imp
.then(wasm => {
mod = wasm;
addCounter();
let b = document.getElementById('add-counter');
if (!b) throw new Error('Unable to find #add-counter');
b.addEventListener('click', ev => addCounter());
})
.catch(console.error);
function addCounter() {
let ctr = mod.Counter.new(randomChar(), 0);
counters.push(ctr);
update();
}
function update() {
let container = document.getElementById('container');
if (!container) throw new Error('Unable to find #container in dom');
while (container.hasChildNodes()) {
if (container.lastChild.id == 'add-counter') break;
container.removeChild(container.lastChild);
}
for (var i = 0; i < counters.length; i++) {
let counter = counters[i];
container.appendChild(newCounter(counter.key(), counter.count(), ev => {
counter.increment();
update();
}));
}
}
function randomChar() {
console.log('randomChar');
let idx = Math.floor(Math.random() * (chars.length - 1));
console.log('index', idx);
let ret = chars.splice(idx, 1)[0];
console.log('char', ret);
return ret;
}
function newCounter(key, value, cb) {
let container = document.createElement('div');
container.setAttribute('class', 'counter');
let title = document.createElement('h1');
title.appendChild(document.createTextNode('Counter ' + key));
container.appendChild(title);
container.appendChild(newField('Count', value));
let plus = document.createElement('button');
plus.setAttribute('type', 'button');
plus.setAttribute('class', 'plus-button');
plus.appendChild(document.createTextNode('+'));
plus.addEventListener('click', cb);
container.appendChild(plus);
return container;
}
function newField(key, value) {
let ret = document.createElement('div');
ret.setAttribute('class', 'field');
let name = document.createElement('span');
name.setAttribute('class', 'name');
name.appendChild(document.createTextNode(key));
ret.appendChild(name);
let val = document.createElement('span');
val.setAttribute('class', 'value');
val.appendChild(document.createTextNode(value));
ret.appendChild(val);
return ret;
}