トピックの説明
次の仮想DOMのデータ構造を前提として、単純な仮想DOMを実装し、それをターゲットのDOMツリーにレンダリングする方法
// 样例数据
let demoNode = ({
tagName: 'ul',
props: {
'class': 'list'},
children: [
({
tagName: 'li', children: ['douyin']}),
({
tagName: 'li', children: ['toutiao']})
]
});
オブジェクトを次のようにレンダリングする関数render
を作成しますdemoNode
dom
<ul class="list">
<li>douyin</li>
<li>toutiao</li>
</ul>
達成
/*
* @Params:
* tagName(string)(requered)
* props(object)(optional)
* children(array)(optional)
* */
function Element({
tagName, props, children}){
if(!(this instanceof Element)){
return new Element({
tagName, props, children})
}
this.tagName = tagName;
this.props = props || {
};
this.children = children || [];
}
これにより、仮想ツリーElement
を任意に構築できます。DOM
しかし、問題があります。仮想は結局仮想であり、ページ上にレンダリングする必要があります。そうしないと、役に立たなくなります。。
それをどのように提示しますか?
上記から、これはツリーであることがわかっているのでDOM
、トラバースすることで実際のノードを1つずつ作成できます。
createElement;
createTextNode;
これはツリーであるため、ツリー構造には2つのトラバーサルしかありません。
- 深さ優先走査(DFS)
- 実際の状況では幅優先探索(BFS)
を使用する必要がありますがDFS
、なぜですか?
子ノードappend
を親ノードに配置する必要があるため
、を使用して、次のように関数をDFS
実装しましょう。render
Element.prototype.render = function(){
var el = document.createElement(this.tagName),
props = this.props,
propName,
propValue;
for(propName in props){
propValue = props[propName];
el.setAttribute(propName, propValue);
}
this.children.forEach(function(child){
var childEl = null;
if(child instanceof Element){
childEl = child.render();
}else{
childEl = document.createTextNode(child);
}
el.appendChild(childEl);
});
return el;
};
この時点で、仮想DOMを指定された実際のDOMに簡単にレンダリングできます。次のように、アピールul仮想DOMをページ本体にレンダリングするとします。
var elem = Element({
tagName: 'ul',
props: {
'class': 'list'},
children: [
Element({
tagName: 'li', children: ['item1']}),
Element({
tagName: 'li', children: ['item2']})
]
});
document.querySelector('body').appendChild(elem.render());