目录
扩展学习资料
Virtual DOM 是什么【虚拟dom】
React渲染
Virtual DOM VS 原生DOM【vDom是否比原生Dom更高效】
Virtual DOM数据结构
Virtaual DOM Diff【虚拟dom前后比对,更新不同dom的算法】
源码解读
react源码组织方式:
React Stack Reconciler【react 栈 协调】
react v15.6.2 源码
练习
名称 |
链接 |
备注 |
Virtual DOM 定义 |
Virtual DOM and Internals – React |
英文 |
Virtual DOM Node |
Mithril.js |
英文 |
VDom与 DOM 的区别 |
The difference between Virtual DOM and DOM - React Kung Fu |
英文 |
React性能优化:Virtual Dom原理浅析 |
[译] React性能优化:Virtual Dom原理浅析 - 掘金 |
|
[译] Virtual Dom 和 Diff 算法 |
[译] Virtual Dom 和 Diff 算法在 React 中是如何工作的? - 掘金 |
虚拟DOM(virtualdom,VDOM)是一个编程概念,将UI的“虚拟”表示形式保存在内存中,并通过ReactDOM之类的库渲染成“真实”的DOM,这个过程叫做协调。
virtual dom将UI节点抽象成js对象
UI节点抽象:Virtual Dom对HTML Dom的抽象
Learn Once,Write Anywhere:因为提供了对HTML DOM的抽象,所以在Web开发中,通常不需要去调用DOM API。也是因为抽象,所以React也可以开发Native(React Native)。【跨平台性】
Virtual Dom构建UI
构建UI:以我们经常见的Web开发为例,来看下React是怎么通过Virtual DOM渲染成HTML元素的。
class App extends Component {
state = {
text: 'Virtual DOM',
}
render() {
const {text} = this.state;
render (
{text}
)
}
}
通过Virtual DOM 渲染页面
很简单的例子,渲染state遍历text的值。
可以看到React是通过render方法渲染Virtual DOM(这里不考虑优化),从而绘制出真实DOM。意味着,每次修改了state的值就会执行render方法。
Virtual DOM是HTML DOM的映射,基本结构大致是一样的
Virtual DOM渲染成HTML,在流程上会比原生DOM操作多几个步骤
实际应用中,页面的操作逻辑会比较复杂频繁,多次频繁操作Dom会导致页面重绘,页面重绘是影响页面性能的关键指标,造成卡顿。react在内部已经做了考虑,所以说会比原生Dom更加高效
对UI节点抽象
在Virtual DOM中,对HTML节点进行抽象。用JS对象的形式表示HTML。
改变了过去对HTML节点的理解。
呈现在用户面前的页面就是一个复杂的递归对象。
const globaldom = {
tagName: 'html',
children: [
{
tagName: 'head',
}, {
tagName: 'body',
children: [{
tagName: 'div',
attributes: {
className: 'test'
}
}]
}
]
}
HTML DOM是个完整的树,常规树遍历的时间复杂度是n³,正是vdom对HTMLdom节点层次的划分,使得HTML树在Vdom中遍历的时间复杂度降为n0这也是Vdom高效的原因之一。
Virtual DOM Diff是体现其性能/维护性的重要过程
react源码:diff 添加子节点
createChild: function (child, afterNode, mountImage) {
return makeInsertMarkup(mountImage, afterNode, child._mountIndex);
},
react源码:diff删除子节点
removeChild: function (child, node) {
return makeRenove(child, node);
},
react源码:diff移动子节点【截取片段】
// 老节点和新节点相等,说明是移动
if(prevChild === nextChild) {
updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));
lastIndex = Math.max(prevChild._mountIndex, lastIndex);
prevChild._mountIndex = nextIndex;
}
moveChild: function (child, afterNode, toIndex, lastIndex) {
// 原节点所在的挂载顺序数 < 更新后所在的顺序数
if (child._mountIndex < lastIndex) {
return makeMove(child, afterNode, toIndex);
} else {
// 不移动它,而是把它后面应该在前面的节点移动到它前面去
}
}
我们应该规避如图示例,将最后一个节点移动到最前面。【这种操作显得不那么高效】
react源码比较复杂,不直观【相对开发来说】;
react的移动、创建、删除并不是在react包中实现的,而是在react dom这个包中实现的。【动态挂载技术】
render -> Virtual DOM Diff->commit【更新】
总结
1.Virtual DOM不仅仅是抽象了HTML Dom操作,更多的是抽象了UI节点,其次带来一种编程理念:数据驱动视图。
Virtual DOM本身的抽象性也使得跨平台成为了可能。
2.如何看待VDom比原生Dom更加高效?
(1)高效的Diff算法实现更新
(2)可维护性和编程思维方面
阅读React源码 React v15.6.2 重点阅读 react-dom ReactMultiChild.js(react-dom/lib/ReactMultiChild.js) 源码。
产出: