@芥末的糖-----虚拟DOM的理解

2018-11-17  本文已影响0人  芥末的糖

为什么要用React

1 使用组件化开发方式,符合现代Web开发的趋势
2 技术成熟,社区完善,配件齐全,适用于大型Web项目(生态系统健全)
3 由Facebook专门的团队维护,技术支持可靠
4 ReactNative - Learn once, write anywhere: Build mobile apps with React
5 使用方式简单,性能非常高,支持服务端渲染
6 React非常火,从技术角度,可以满足好奇心,提高技术水平;从职业角度,有利于求职和晋升,有利于参与潜力大的项目

1.什么是虚拟DOM(Virtual DOM)

虚拟DOM(VDOM)是一种编程概念,是指虚拟的视图被保存在内存中,并通过诸如ReactDOM这样的库与“真实”的DOM保持同步。这个过程被称为和解

这种编程方法使用了React的声明式API:你需要告诉React你想让视图处于什么状态,React则负责确保DOM与该状态相匹配。因此你在构建你的应用时不必自己去完成属性操作、事件处理、DOM更新,React会替你完成这一切。

由于“虚拟DOM”更像一种模式而不是特定的技术,有时候我们也会用它表示其他的意思。在React的世界中,由于 “虚拟DOM” 和 React元素 都是用于表示视图的对象,因此常常被关联在一起。然而React也使用被称为“fibers”的对象来存放组件树的附加信息。在React中,它们也被认为是“虚拟DOM”实现的一部分。

React中有两种假定:
1 两个不同类型的元素会产生不同的树(根元素不同结构树一定不同)
2 开发者可以通过key属性指定不同树中没有发生改变的子元素

2.为什么要用虚拟DOM

MVC

随着应用程序越来越复杂,需要在JS里面维护的字段也越来越多,需要监听事件和在事件回调用更新页面的DOM操作也越来越多,应用程序会变得非常难维护。后来人们使用了 MVC、MVP 的架构模式,希望能从代码组织方式来降低维护这种复杂应用程序的难度。但是 MVC 架构没办法减少你所维护的状态,也没有降低状态更新你需要对页面的更新操作(前端来说就是DOM操作),你需要操作的DOM还是需要操作,只是换了个地方。

MVVM

为什么不做一个东西可以让视图和状态进行绑定,状态变更了视图自动变更,就不用手动更新页面了。这就是后来人们想出了 MVVM 模式。最大的问题就是这样做会很慢,因为即使一个小小的状态变更都要重新构造整棵 DOM,性价比太低;

虚拟DOM结局的问题

1.维护状态,更新视图
2.局部更新,避免DOM整棵树更新

3.实现原理

DOM 树上的结构、属性信息我们都可以很容易地用 JavaScript 对象表示出来:


var element = {
  tagName: 'ul', // 节点标签名
  props: { // DOM的属性,用一个对象存储键值对
    id: 'list'
  },
  children: [ // 该节点的子节点
    {tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
    {tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
    {tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
  ]
}

上面对应的HTML写法是:

<ul id='list'>
  <li class='item'>Item 1</li>
  <li class='item'>Item 2</li>
  <li class='item'>Item 3</li>
</ul>

这就是所谓的 Virtual DOM 算法。包括几个步骤:
1.用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树

2.然后用新的树和旧的树进行比较,记录两棵树差异把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。

3.可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。

4.CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。

diff算法映射总结

  1. 根元素不同,渲染新树
  2. 只更新不同的属性
  3. 子元素没有key值时,在头部插入一个节点,则都删除重新创建,如果有key值,则只会更新你插入的节点,原有节点只是移动位置

算法实现

[diff算法实现地址](https://segmentfault.com/a/1190000012921279

上一篇下一篇

猜你喜欢

热点阅读