思路一
- state 数据
- 模板 (JSX)
- 数据和模板相结合,生成真实的 DOM,来显示
- state 发生改变
- 数据 + 模板结合,生成真实的 DOM,替换原始的 DOM
缺陷:生成和替换非常消耗性能
思路二
- state 数据
- 模板 (JSX)
- 数据和模板相结合,生成真实的 DOM,来显示
- state 发生改变
- 数据 + 模板结合,生成真实的 DOM,但是并不替换原始的 DOM
- 新的 DOM (
DoucumentFragment
) 和原始 DOM 做对比,找寻差异 - 找出 input 框发生了变化
- 只用新的 DOM 中的 input 元素,替换掉老的 DOM 中的 Input 元素
缺陷:DOM 做对比性能很消耗性能
react —— 虚拟 DOM
- state 数据
- 模板 (JSX)
- 数据 + 模板结合,生成虚拟的 DOM(一个 JS 对象,用来描述真实的 DOM)
真实 DOM:
<div id='fun'> <span> hello </span> </div>
虚拟 DOM:['div', { id:'fun' }, ['span', { }, 'hello']]
- 用虚拟 DOM 生成真实的 DOM,来显示
- state 发生改变
- 数据 + 模板结合,生成新的虚拟 DOM(提升了大量的性能)
- 比较原始和新的虚拟 DOM(例如:找到 span 内容的区别)(对比 JS 对象,提升了大量的性能)
- 直接操作 DOM,改变 span 中的内容
JSX 转变为 DOM
// 在 JSX 中两者区别一样,React.createElement 用来生成 DOM 节点
return <div id='fun'>hello</div>
return React.createElement('div', { id: 'fun' }, 'hello')
Diff 算法(比较虚拟 DOM)
同层比对,遇到不同,后面不在比对,整体替换
React 通过 updateDepth 对虚拟 DOM 树进行层级控制。
对树分层比较,两棵树只对同一层次节点 进行比较。如果该节点不存在时,则该节点及其子节点会被完全删除,不会再进一步比较。
只需遍历一次,就能完成整棵 DOM 树的比较。
diff 只简单考虑同层级的节点位置变换,如果是跨层级的话,只有创建节点和删除节点的操作
如上图所示,以 A 为根节点的整棵树会被重新创建,而不是移动,因此 官方建议不要进行 DOM 节点跨层级操作,可以通过 CSS 隐藏、显示节点,而不是真正地移除、添加 DOM 节点
优点
- 性能提升
- 使得跨端应用得以实现(React Native)