我们都知道 react 中 state 发生改变, render 函数重新执行渲染页面
那么自己实现这个功能的思路?
- 定义 state,有了数据
- 有一个模板
- 数据 + 模板 结合, 生成真实 dom, 显示
- state 发生改变
- 数据 + 模板 结合, 生成真实 dom, 替换原始的 dom
缺陷:
第一次生成了一个完整的 DOM 片段,
第二次生成了一个完整的 DOM 片段,
第二次的 DOM 替换第一次的 DOM, 非常耗性能(仅有一部分数据发生改变, 但是要生成和替换全部的 DOM 片段)
改良:
- 定义 state,有了数据
- 有一个模板
- 数据 + 模板 结合, 生成真实 DOM, 显示
- state 发生改变
- 数据 + 模板 结合, 生成真实的 DOM, 并不直接替换原始的 DOM,
- 新的 DOM (在内存里的 DocumentFragment) 和原始的 DOM 作比对, 找差异
- 找出 发生改变的某一部分比如 input 框发生了变化
- 只用新的 DOM 中的 input 元素, 替换掉老 DOM 中的 input 元素
改良版缺陷:
性能的提升并不明显
React 采用的方案:
- 定义 state,有了数据
- 有一个模板
- 数据 + 模板 结合, 生成真实 DOM, 显示
- 生成虚拟 DOM(虚拟 DOM 就是一个 js对象, 用它来描述真实 DOM)
<div id='abc'><span>hello world</span></div>
就类似
[
'div',
{
id: 'abc'},
['span', {
}, 'hello world']
]
- state 发生变化
- 数据 + 模板 生成新的虚拟 DOM (极大地提升性能)
<div id='abc'><span>hello world</span></div>
就类似
[
'div',
{
id: 'abc'},
['span', {
}, 'bye bye']
]
- 比较原始虚拟 dom和原始虚拟 dom的区别, 找到区别是 span 中内容
- 直接操作 DOM, 改变 span 中的内容
总结: 减少了真实 dom 创建操作和真实 dom 对比, 取而代之以 js 对象代替
Tip:
真实 react 机制中, 上面 3和 4步是反过来的
- 定义 state,有了数据
- 有一个模板
- 数据 + 模板生成虚拟 DOM(虚拟 DOM 就是一个 js对象, 用它来描述真实 DOM)
- 用虚拟 DOM 的结构生成真实的 DOM, 来显示
- state 发生变化
- 数据 + 模板 生成新的虚拟 DOM (极大地提升性能)
- 比较原始虚拟 dom和原始虚拟 dom的区别, 找到区别是 span 中内容
- 直接操作 DOM, 改变 span 中的内容
JSX --> React.createElement --> 虚拟 DOM(JS 对象) --> 真实的 DOM
虚拟 DOM 好处:
- 性能提升了(dom 比对变成了 js 对象比对)
- 使得跨端应用得以实现 React Native (虚拟 dom 可以在原生应用中被识别, 在哪里都可以运行, 如果在原生应用可以把虚拟 dom 转化成原生应用组件)