深入认识 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
深入认识VDOM
By giscafer
深入认识VDOM
技术交流分享
- 400