动手实现数据双向绑定React Dom(4)

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产生变化也不会产生重新渲染,举个例子,

{{demo1}}

,假设demo1变量数值是hello world,那么渲染出来的dom 即是

hello world

,当我们换了一个变量demo2,即

{{demo2}}

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);

5.代码实现
http://codepen.io/youyudehexie/pen/BjQZEo

你可能感兴趣的:(动手实现数据双向绑定React Dom(4))