見出し画像

Rust Webassembly + node/express DOM操作する例 #Rust #Webassembly #javascript #node

■ 概要:

前のRust Webassembly (下記 wasm) 関係で
機能の実践編で、
express でCRUD実装の、一部表示機能をwasm で実装する例となります。

■ 前の関連ページ
https://note.com/knaka0209/n/n0da6740b3c7c


■ 環境

Rust
rustc 1.46.0
cargo 1.46.0
wasm-pack
node 12.18.3
express

■ プロジェクト作成、ビルド

cargo generate --git https://github.com/rustwasm/wasm-pack-template

wasm-pack build --target=web

■ 実装など

・Cargo.toml

[package]
name = "wasm-crud-1"
version = "0.1.0"
authors = ["naka"]
edition = "2018"

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

[features]
default = ["console_error_panic_hook"]

[dependencies]
wasm-bindgen = "0.2.63"
js-sys = "0.3.44"

# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.6", optional = true }

# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.5", optional = true }


[dependencies.web-sys]
version = "0.3.4"
features = [
 'console',
 'Document',
 'Element',
 'HtmlElement',
 'Node',
 'Window',
]

[dev-dependencies]
wasm-bindgen-test = "0.3.13"

[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

・Rust ,  lib.rs

id指定し、DOM追加します。


#[wasm_bindgen]
pub fn wasm_put_item(id_name: &str, title: &str, id_val: &str) -> Result<(), JsValue>{
   let document = web_sys::window().unwrap().document().unwrap();
   let entry_point = document.get_element_by_id(id_name).unwrap();
   let val = document.create_element("li")?;
   let s_elm = format!("<div class='div_post_wrap'>
       <a href='/tasks/show/{}'>
           <h3 class='h3_title'>{}</h3>
       </a>
       <span>ID :{}</span>
       <a href='/tasks/edit/{}'> [ edit ] </a>
       <hr />
   </div>", id_val , title, id_val, id_val );
   val.set_inner_html(&s_elm );
// console::log_1(&JsValue::from_str( &s_elm ));
   val.set_inner_html(&s_elm );
   entry_point.append_child(&val)?;

   Ok(())
}

■ express

CRUDリストの画面
views/tasks/index.ejs
JS配列から、wasm_put_itemでDOM追加します。

<script type="module">
import init, * as wasm from '/pkg/wasm_crud_1.js';
var task_items = [];

var TaskIndex = {
   get_items: async function(){
       await axios.get("/api/tasks_index").then(res =>  {
           task_items = res.data.docs
       })
       this.dispRow();
   },
   dispRow: async function(){
       await init();
       if(task_items instanceof Array){
//            console.log(task_items );
           task_items.map(function(object, index){
               wasm.wasm_put_item("ul_post_wrap", String(object.title), String(object.id));
           })
       }
   },
}
//
$(function(){
   TaskIndex.get_items();
});
</script> 

■ 補足、json形式で、DOM操作する方法を追加しました。2020/09/05

・Cargo.toml , serde, serde_json を追加

[dependencies]
wasm-bindgen = "0.2.63"
js-sys = "0.3.44"
serde = { version = "1.0.100", default-features = false }
serde_json = "1.0"

・lib.rs


#[wasm_bindgen]
pub fn wasm_put_json(id_name: &str, json: &str) -> Result<(), JsValue>{
   let v: Value = serde_json::from_str( json ).unwrap();
   let tmp_title = v["title"].to_string();
   let title = tmp_title.replace('"', "");
   let id_val = format!("{}", &v["id"]  );
//    console::log_1(&JsValue::from_str( &title ));

   let document = web_sys::window().unwrap().document().unwrap();
   let entry_point = document.get_element_by_id(id_name).unwrap();
   let val = document.create_element("li")?;
   let s_elm = format!("<div class='div_post_wrap'>
       <a href='/tasks/show/{}'>
           <h3 class='h3_title'>{}</h3>
       </a>
       <span>ID :{}</span>
       <a href='/tasks/edit/{}'> [ edit ] </a>
       <hr />
   </div>", id_val , title, id_val, id_val );
   val.set_inner_html(&s_elm );
   entry_point.append_child(&val)?;

   Ok(())
}

・express, wasm_put_json呼びます

    dispRow:async function(){
       await init();
       if(task_items instanceof Array){
           task_items.map(function(object, index){
               var json = JSON.stringify( object );
//console.log(json );
               wasm.wasm_put_json("ul_post_wrap", String(json) );
           })
       }
   },


■ 参考のコード

・Rust コード

・express

■ 画面
一覧画面です

画像1








いいなと思ったら応援しよう!