React.js 已经成了当红炸子鸡,不会React.js都不好意思说自己会前端了。其中,虚拟DOM是其主要的特性。
那么它相对于其他双向绑定模有什么异同吗?
无论是angular还是vue,对于动态绑定的重新渲染,取决与model的数值变化,而react则是虚拟树的比较。我们来看看react的渲染流程。
1.创建一棵虚拟的dom树。
2.渲染到真实dom中。
3.model数据变化,告诉react重新在内存中生成新的虚拟dom树。
4.新的虚拟dom树与旧的dom树进行对比,提取两棵树不同的节点部分。
5.将变化部分,渲染到真实的dom上。
来谈谈react.js的优势
1.react关注的是渲染效果,如果渲染效果一样的情况,哪怕model产生变化也不会产生重新渲染,举个例子,<p>{{demo1}}</p>
,假设demo1变量数值是hello world
,那么渲染出来的dom 即是 <p>hello world</p>
,当我们换了一个变量demo2
,即<p>{{demo2}}</p>
demo2`的数值也是"hello world",对于传统的双向绑定框架,肯定认为数值变化了,需要重新渲染,而react因为是直接对新旧树之间的比较,两个树一样旧不用重新渲染了。
2.简化了框架的更新逻辑,在前文中,可以看出来我直接让model属性与dom元素绑定了,当我修改model属性的时候,能够直接修改dom元素,能做到O(1)的搜索,这是我对mvvm的简单优化,但对于一个复杂mvvm框架来说,算法可没有那么容易,dom结构随时都可能被删除,添加各种操作,稍微不慎就会导致更新失败或无法做到优化,对于虚拟dom稳定控制在o(n)内,无论操作有多么复杂。
3.以上都是我个人理解reactjs的优势,知乎里面也有精彩的讨论,可以参考
https://www.zhihu.com/question/31809713
代码实现
1.构造虚拟dom树系统,是比较复杂的代码,足够写一篇文章,由于不是本文的重点,这里采用的是开源项目
https://github.com/livoras/simple-virtual-dom
主要使用的是
var svd = require('simple-virtual-dom')
var el = svd.el //构造dom树元素
var diff = svd.diff // 对新树与就树之间做对比,找出不同的地方
var patch = svd.patch // 将dom树变动部分变化,应用到原来的dmo上
2.生成虚拟dom树
genVTree: function (model) {
return el('div', {'id': 'container'}, [
el('span', [model.time])
]);
},
3.插入虚拟dom树到真实dom
var vTree = this.genVTree(this.model);
this.tree = vTree;
this.root.appendChild(vTree.render());
4.产生数据变化,当数据变化的时候,重新生成虚拟dom树,与旧的dom树进行比较,找出不同的dom部分,并将该部分的改动应用到真实dom树里。
setState(object) {
var self = this;
var oldTree = this.tree;
Object.keys(object).forEach(function (key) {
self.model[key] = object[key];
});
var newTree = this.genVTree(this.model);
this.tree = newTree;
var patches = diff(newTree, oldTree);
patch(this.root, patches);
},
setInterval(function () {
demo.setState({time: Date()})
}, 1000);