假如我们想自己实现一个React
,简单底层实现:
1.state数据
2.JSX 模板
3.数据 + 模板 结合,生成真实的DOM,来显示
4.state 发生改变
5.数据 + 模板 结合,生成真实的DOM,替换原始的DOM
缺陷:
第一次生成了一个完整的DOM片段
第二次生成了一个完整的DOM片段
第二次的DOM替换第一次的DOM,非常耗性能(实际上可能只有片段中的一小部分需要改变)
那我们应该如何改良呢?
1.state数据
2.JSX 模板
3.数据 + 模板 结合,生成真实的DOM,来显示
4.state 发生改变
5.数据 + 模板 结合,生成真实的DOM,并不直接替换原始的DOM
6.新的DOM和原始的DOM做对比,找差异
7.找出发生了变化的地方
8.只用新的DOM中变化的地方,来替换掉老的DOM中的对应位置
缺陷:
性能的提升并不明显
React
提出了第三种方案——虚拟DOM
1.state 数据
2.JSX 模板
3.数据 + 模板结合,生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)
[ 'div', {id: 'abc'}, [ 'span', {}, 'hello world' ] ]
3.用虚拟DOM的结构生成真实的DOM,来显示
<div id='abc'><span>hello world</span></div>
5.state 发生变化
6.数据 + 模板 生成新的虚拟DOM(极大的提升了性能)
[ 'div', {id: 'abc'}, [ 'span', {}, 'bye bye' ] ]
- 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(极大的提升了性能)
8.直接操作DOM,改变span中的内容
React
的JSX解析过程
JSX -> createElement -> 虚拟DOM(JS对象)->真实的DOM
例如:
return <div><span>item</span></div>
等同于
return React.createElement('div',{},React.createElement('span',{},item));
虚拟DOM带来了什么好处
1.性能提升了
2.它使得跨端应用得以实现(React Native
),因为虚拟DOM在原生应用和网页中都能够被识别。
Diff算法
同层比对,如果一层不同,则直接替换,不会做下一层的比对,这样性能比较好
setState是异步的
是为了提升底层的性能。假设我连续调用三次setState
,变更三组数据,由于setState
是异步的,React
可以把三次setState
合并成一次,只去做一次虚拟DOM的比对,就可以省去两次虚拟DOM的比对带来的性能的耗费。
key值能用index吗?
在react
中,我们能不用index
做key
值就尽量不用index
做key
值,因为这样是不稳定的,我们应该尽量用稳定的不会改变的key
值。