深入认识 Virtual DOM

DOM

Document Object Model

深入了解 Virtual DOM

DOM

Document Object Model

跨平台
语言无关
结构化文档

浏览器是如何呈现web页面

频繁操作DOM存在性能问题

如何解决 DOM 性能问题?

 解决DOM 性能方式

  • Shadow DOM

  • Virtual DOM

  • 算法

  • 少或不操作DOM

Shadow DOM

#shadow-root
  <style>
    #panels {
      box-shadow: 0 2px 2px rgba(0, 0, 0, .3);
      background: white;
      ...
    }
    #tabs {
      display: inline-flex;
      ...
    }
  </style>
  <div id="tabs">
    ...
  </div>
  <div id="panels">
    ...
  </div>

Virtual DOM

// VNODE:a JS object representation of a single DOM node with it’s properties and children
{
   "nodeName": "",
   "attributes": {},
   "children": []
}
{
   "nodeName": "input",
   "attributes": {
    "type": "text",
    "placeholder": "Search",
    "autofocus":"true",
    "onChange": ""
   },
   "children": []
  }

<input type="text" placeholder="Search" autofocus="true">

VDOM 对比图

为什么VDOM会更快?

有两个问题需要解决

  • 何时重新渲染DOM

  • 如何有效的实现VDOM渲染

何时重新渲染

怎么知道数据被改变了呢?

  • Dirty checking
  • Observable

怎么做才能真正快速

  • 高效的 diff算法
  • 批处理DOM的读写操作
  • 只针对子树进行有效的更新
  • 使用可观察(Observable )的而不是脏检查来检测更改

总结

Virtual DOM  是一种技术和一组库/算法,它允许我们通过避免直接使用 DOM 和只使用模拟DOM 树的轻量级 JavaScript 对象来提高前端性能。

概念懂了,再深入认识一下

Virtual DOM 在 React 中的实现

Virtual DOM 在 React 中的实现

  • 如果父状态更改,重新渲染所有子状态 如果父组件状态变化了,ReactJS 会重新渲染所有子组件,不管子组件状态是否发生变化,所以 ReactJS 提供了 shouldComponentUpdate() 生命周期方法,用来有效的减少一些没必要的渲染,提升性能
  • 广度优先搜索(BFS)diff算法
  • Reconciliation  确定 Real DOM 哪些需要更新的过程:1、不同的元素类型将产生不同的树;2、开发人员可以通过设置key属性来告知 ReactJS 哪些子元素可能是稳定的。详细见官方文档docs/reconciliation
  • 批量更新(Batch Update) ReactJS 等待所有的事件循环完成,才批量将对比好的需要更新的元素更新到 Real DOM

查找两个Virtual DOM的不同之处:

Demo

WTF is JSX

the code you write

/** @jsx h */
// https://github.com/hyperhype/hyperscript

let foo = <div id="foo">Hello!</div>;  

the code you run

var foo = h('div', {id:"foo"}, 'Hello!');  

Understanding JSX

JSX 只是语法糖,目的是为了使得 HTML 和 JavaScript 更好的交互

Demo

HTML in JS

VDOM的内部工作原理

 TODO App Tree

Rendering process 

Title Text

the code you write

//Mount to real DOM
render(<FilteredList/>, document.getElementById(‘app’));

the code you run

//Converted to "h":
render(h(FilteredList), document.getElementById(‘app’));

渲染到Real DOM

Preact的VDOM算法流程图

应用第一次加载

此时,我们有一个VNode,它有一个“div” parentNode,它有一个“input”和一个“List”子节点。

循环创建children

在创建“input”之后,因为它没有任何子元素,所以它不会立即循环并创建“List”。 相反,它会首先将“input”附加到父“div”中,然后返回到进程“List”

List Comp Render

Render Order

思考:日常开发如何优化

完!!!

深入了解 Virtual DOM

Made with Slides.com