将虚拟DOM转变成为真实的DOM
现在我们有了一个纯粹的JS对象来代表一个DOM树,下一步要做的是按照这个虚拟DOM来创造一个真的DOM。在此之前需要先做一些约定:
- 以美元符号
$
开头的变量代表真实DOM。 - 变量
node
代表虚拟DOM。 - 只能有一个根节点。
好,我现在要写一个按照虚拟DOM来创造真实DOM的函数,名为createElement(...)
,这个函数接收一个虚拟DOM作为参数,返回一个真实DOM。为了简便起见,暂时先不考虑props
属性和children
属性,这些东西以后再完善。
function createElement(node){
if(typeof node ==='string'){
return document.createTextNode(node);
}
const $el = document.createElement(node.type);
node.children.map(createElement).forEach($el.appendChild.bind($el));
return $el;
}
这个createElement方法是不是看起来有点复杂,这是因为里面加了一些奇技淫巧,事实上如果你自己用本方法,可以写出来虽然冗长但是通俗易懂的实现,我写成这样是为了排版好看。说白了,这个createElement方法只是一个递归调用,使用了document对象的createElement方法和createTextNode方法以及DOM对象的appendChild方法,只有这三个方法而已。
如果你对上面这段代码很困惑,那么没关系,请跳过,这篇文章主要介绍的是思路,而不是具体实现。
好了,现在我可以根据一个虚拟DOM来生成一个真实的DOM了,来看看我现在的代码:
/** @jsx h */
function h(type, props, ...children) {
return { type, props, children };
}
function createElement(node){
if(typeof node ==='string'){
return document.createTextNode(node);
}
const $el = document.createElement(node.type);
node.children.map(createElement).forEach($el.appendChild.bind($el));
return $el;
}
const a = (
<ul class="list">
<li>item 1</li>
<li>item 2</li>
</ul>
);
const DOM = createElement(a);
const root = document.getElementById("root");
root.appendChild(DOM)
现在这个代码可以顺利地将虚拟DOM产生为一个真实DOM并且显示在页面上了。
image.png下一部分会写虚拟DOM的diff算法。其实就是如何比对两个虚拟DOM,找出不同,并且在真实DOM上做出反应。
网友评论