React框架现在用的人非常多,React为何如此受欢迎?我想原因是引入了虚拟DOM的概念,从而使得性能有所提升吧。为什么引入虚拟DOM性能就有提升了?下面我想来说一说虚拟DOM的原理。
什么是虚拟DOM?
React中,先将真实的DOM抽象成一个JavaScript对象,也就是虚拟DOM。比如,我们可以构造一个虚拟DOM:
var element = {
element: 'ul',
props: {
id:"ulist"
},
children: [
{ element: 'li', props: { id:"first" }, children: ['这是第一个List元素'] },
{ element: 'li', props: { id:"second" }, children: ['这是第二个List元素'] }
]
}
为了后面可以调函数来将虚拟DOM对象转换成真实DOM,我们用一个构造函数将上面的对象封装下:
function Element( tagname, props, children )
{
this.TagName = tagname;
this.props = props;
this.children = children;
}
var u = new Element( 'ul', { id: 'ulist'}, [
new Element( 'li', { id:"first" }, ['这是第一个List元素']),
new Element( 'li', { id:"first" }, ['这是第一个List元素'])
]);
这时候的e 就是一个Element对象,里面包含TagName,props以及children属性,并且children也是Element对象。下来我们来思考下如何将这个对象转换成真实的DOM结构。
Element.prototype.render = function( ) {
var d = document.createElement( this.TagName );
for( key in this.props) {
d.setAttribute( key, this.props[key] );
}
this.children.forEach( function(child){
if(child instanceof Element) {
tnode = child.render();
}
else
{
tnode = document.createTextNode(child);
}
d.appendChild(tnode);
})
return d;
}
let ele = u.render();
document.body.appendChild(ele);
这样就把我们构造的虚拟DOM对象转换成真实DOM,并呈现到页面上了。
React中虚拟DOM原理
在React中,也有一个render函数来将虚拟DOM树,并且,React中有state转移的过程,所以每次state有变化之后,就会触发render函数,重新构造一个虚拟DOM树。对比新旧虚拟DOM树的差别,记录下差异,然后只针对差异部分对应的真实DOM进行操作。
如何进行新旧虚拟DOM树的对比呢?
这里采用的是Diff算法。Diff算法比较复杂,主要的思路是这样的。
首先,每一次生成的虚拟DOM树上的各个节点都对应唯一的一个id,当第二次生成了新的DOM树时,对原来树上的每一个节点对比新树上对应节点,如果不同,就记录下来这个差异。同时,差异也分为很多种:
替换节点;
修改属性;
对文本内容修改
移动、删除、增加节点;
对每一类记录下差异之后,针对不同的差异进行不同的操作。
比如,替换节点就需要调原生JS的repaceChild()接口;对于修改属性,则要调setAttribute()接口等等。
至于具体算法的细节,暂时还没有深究,希望有兴趣的可以一起交流。