Rust로 가상 DOM 구현 -1
이번에
가상 DOM 트리의 노드를 구현하고 이를 그리는 함수를 구현합니다.
또한, 이 기사의 방침으로서, Result
나 Option
에 대해서는 panic 하지 않을 것임에 틀림없다고 하는 전제로 점점 unwrap
하고 있습니다. 만약 실제로 이 샘플을 참고로 제품을 개발한다면, 에러 처리를 넣는 것이 좋을까 생각합니다.
궁극적으로 다음 예제와 같은 출력을 얻습니다.
실행 결과 예:
준비
준비 합니다.
그런 다음 cargo.toml에 다음 내용을 추가합니다.
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies.wasm-bindgen]
version = "0.2.51"
[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
'Node',
'Text',
]
구현
가상 DOM 트리의 노드 만들기
// lib.rs
enum VirtualNode {
Text(&'static str),
Element {
tag_name: &'static str,
children: Vec<VirtualNode>,
},
}
가상 DOM 트리의 노드VirtualNode
를 구현합니다. <h1>Hello World</h1>
를 예로 들어, <h1>
태그에 해당하는 것은 VirtualNode::Element
이고 Hello World
에 해당하는 것은 VirtualNode::Text
입니다. 이것을 Rust 코드로 나타내면
VirtualNode::Element {
tag_name: "h1",
children: vec![VirtualNode::Text("Hello World")],
}
같아요.
우선, VirtualNode::Element
에는 태그명을 판별하기 위한 tag_name
와, 아이 요소의 리스트를 보관 유지하는 children
만을 구현합니다.
가상 DOM 그리기
// lib.rs
fn render(document: &web_sys::Document, virtual_node: VirtualNode) -> web_sys::Node {
match virtual_node {
VirtualNode::Text(text) => document.create_text_node(text).into(),
VirtualNode::Element { tag_name, children } => {
let element = document.create_element(tag_name).unwrap();
for child in children {
element.append_child(&render(document, child));
}
element.into()
}
}
}
일단 차이를 취하지 않고 DOM을 재구성하는 함수를 구현해 보겠습니다. 깊이 우선 재귀를 돌리고 있습니다. 일일이web_sys::window().unwrap().document().unwrap().create_text_node(text)
등이라고 쓰는 것이 싫었기 때문에, render
의 제1 인수에 document: &web_sys::Document
를 취해 버렸습니다. 에러 처리도 코드의 머리로 1회하면 끝나므로 이쪽이 좋을까 생각합니다.
match
에 의해 VirtualNode
가 Text
인지 Element
인지 판정합니다. Text
이면 document.create_text_node
로 노드를 만듭니다. Element
이면 document.create_element
로 노드를 만들고 append_child
로 자식 노드를 추가했습니다.
document.create_text_node(text)
의 반환 값 유형은 web_sys::Text
이고 document.create_element(tag_name).unwrap()
의 반환 값은 web_sys::Element
입니다. 함께 into()
형식을 web_sys::Node
로 변환합니다.
지금까지 할 수있는 것
위의 내용에 extern
, render
함수를 실행하여 엔트리 포인트가되는 요소에 결과를 반영하는 main
함수 등을 추가했습니다.
// lib.rs
extern crate wasm_bindgen;
extern crate web_sys;
use wasm_bindgen::prelude::*;
enum VirtualNode {
Text(&'static str),
Element {
tag_name: &'static str,
children: Vec<VirtualNode>,
},
}
fn render(document: &web_sys::Document, virtual_node: &VirtualNode) -> web_sys::Node {
match virtual_node {
VirtualNode::Text(text) => document.create_text_node(text).into(),
VirtualNode::Element { tag_name, children } => {
let element = document.create_element(tag_name).unwrap();
for child in children {
element.append_child(&render(document, child));
}
element.into()
}
}
}
#[wasm_bindgen(start)]
pub fn main() {
let document = web_sys::window().unwrap().document().unwrap();
let entry_point = document.get_element_by_id("app").unwrap();
let node = VirtualNode::Element {
tag_name: "h1",
children: vec![VirtualNode::Text("Hello World")],
};
entry_point
.parent_node()
.unwrap()
.replace_child(&render(&document, &node), &entry_point);
}
실행
npm start
localhost:8080 에 액세스하면 Hello World 라고 표시됩니다.
Reference
이 문제에 관하여(Rust로 가상 DOM 구현 -1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/SoundRabbit/items/29ae8e5bcccfec41a626
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
준비 합니다.
그런 다음 cargo.toml에 다음 내용을 추가합니다.
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies.wasm-bindgen]
version = "0.2.51"
[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
'Node',
'Text',
]
구현
가상 DOM 트리의 노드 만들기
// lib.rs
enum VirtualNode {
Text(&'static str),
Element {
tag_name: &'static str,
children: Vec<VirtualNode>,
},
}
가상 DOM 트리의 노드VirtualNode
를 구현합니다. <h1>Hello World</h1>
를 예로 들어, <h1>
태그에 해당하는 것은 VirtualNode::Element
이고 Hello World
에 해당하는 것은 VirtualNode::Text
입니다. 이것을 Rust 코드로 나타내면
VirtualNode::Element {
tag_name: "h1",
children: vec![VirtualNode::Text("Hello World")],
}
같아요.
우선, VirtualNode::Element
에는 태그명을 판별하기 위한 tag_name
와, 아이 요소의 리스트를 보관 유지하는 children
만을 구현합니다.
가상 DOM 그리기
// lib.rs
fn render(document: &web_sys::Document, virtual_node: VirtualNode) -> web_sys::Node {
match virtual_node {
VirtualNode::Text(text) => document.create_text_node(text).into(),
VirtualNode::Element { tag_name, children } => {
let element = document.create_element(tag_name).unwrap();
for child in children {
element.append_child(&render(document, child));
}
element.into()
}
}
}
일단 차이를 취하지 않고 DOM을 재구성하는 함수를 구현해 보겠습니다. 깊이 우선 재귀를 돌리고 있습니다. 일일이web_sys::window().unwrap().document().unwrap().create_text_node(text)
등이라고 쓰는 것이 싫었기 때문에, render
의 제1 인수에 document: &web_sys::Document
를 취해 버렸습니다. 에러 처리도 코드의 머리로 1회하면 끝나므로 이쪽이 좋을까 생각합니다.
match
에 의해 VirtualNode
가 Text
인지 Element
인지 판정합니다. Text
이면 document.create_text_node
로 노드를 만듭니다. Element
이면 document.create_element
로 노드를 만들고 append_child
로 자식 노드를 추가했습니다.
document.create_text_node(text)
의 반환 값 유형은 web_sys::Text
이고 document.create_element(tag_name).unwrap()
의 반환 값은 web_sys::Element
입니다. 함께 into()
형식을 web_sys::Node
로 변환합니다.
지금까지 할 수있는 것
위의 내용에 extern
, render
함수를 실행하여 엔트리 포인트가되는 요소에 결과를 반영하는 main
함수 등을 추가했습니다.
// lib.rs
extern crate wasm_bindgen;
extern crate web_sys;
use wasm_bindgen::prelude::*;
enum VirtualNode {
Text(&'static str),
Element {
tag_name: &'static str,
children: Vec<VirtualNode>,
},
}
fn render(document: &web_sys::Document, virtual_node: &VirtualNode) -> web_sys::Node {
match virtual_node {
VirtualNode::Text(text) => document.create_text_node(text).into(),
VirtualNode::Element { tag_name, children } => {
let element = document.create_element(tag_name).unwrap();
for child in children {
element.append_child(&render(document, child));
}
element.into()
}
}
}
#[wasm_bindgen(start)]
pub fn main() {
let document = web_sys::window().unwrap().document().unwrap();
let entry_point = document.get_element_by_id("app").unwrap();
let node = VirtualNode::Element {
tag_name: "h1",
children: vec![VirtualNode::Text("Hello World")],
};
entry_point
.parent_node()
.unwrap()
.replace_child(&render(&document, &node), &entry_point);
}
실행
npm start
localhost:8080 에 액세스하면 Hello World 라고 표시됩니다.
Reference
이 문제에 관하여(Rust로 가상 DOM 구현 -1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/SoundRabbit/items/29ae8e5bcccfec41a626
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
// lib.rs
enum VirtualNode {
Text(&'static str),
Element {
tag_name: &'static str,
children: Vec<VirtualNode>,
},
}
VirtualNode::Element {
tag_name: "h1",
children: vec![VirtualNode::Text("Hello World")],
}
// lib.rs
fn render(document: &web_sys::Document, virtual_node: VirtualNode) -> web_sys::Node {
match virtual_node {
VirtualNode::Text(text) => document.create_text_node(text).into(),
VirtualNode::Element { tag_name, children } => {
let element = document.create_element(tag_name).unwrap();
for child in children {
element.append_child(&render(document, child));
}
element.into()
}
}
}
위의 내용에
extern
, render
함수를 실행하여 엔트리 포인트가되는 요소에 결과를 반영하는 main
함수 등을 추가했습니다.// lib.rs
extern crate wasm_bindgen;
extern crate web_sys;
use wasm_bindgen::prelude::*;
enum VirtualNode {
Text(&'static str),
Element {
tag_name: &'static str,
children: Vec<VirtualNode>,
},
}
fn render(document: &web_sys::Document, virtual_node: &VirtualNode) -> web_sys::Node {
match virtual_node {
VirtualNode::Text(text) => document.create_text_node(text).into(),
VirtualNode::Element { tag_name, children } => {
let element = document.create_element(tag_name).unwrap();
for child in children {
element.append_child(&render(document, child));
}
element.into()
}
}
}
#[wasm_bindgen(start)]
pub fn main() {
let document = web_sys::window().unwrap().document().unwrap();
let entry_point = document.get_element_by_id("app").unwrap();
let node = VirtualNode::Element {
tag_name: "h1",
children: vec![VirtualNode::Text("Hello World")],
};
entry_point
.parent_node()
.unwrap()
.replace_child(&render(&document, &node), &entry_point);
}
실행
npm start
localhost:8080 에 액세스하면 Hello World 라고 표시됩니다.
Reference
이 문제에 관하여(Rust로 가상 DOM 구현 -1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/SoundRabbit/items/29ae8e5bcccfec41a626
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
npm start
Reference
이 문제에 관하여(Rust로 가상 DOM 구현 -1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/SoundRabbit/items/29ae8e5bcccfec41a626텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)