我们知道,当组件的state和props发生变化的时候,render函数就会重新执行,组件就会被重新渲染,这样是性能非常低的。因此,react引入了虚拟DOM.
虚拟DOM是什么呢?虚拟DOM就是一个JS对象,用它来描述真实DOM。
当state发生变化时,render函数会重新执行渲染页面。如果我们自己来做这个功能,那该怎样实现呢?
方案一: 1. 定义一个state,先有数据 2. 有一个模板(render函数中jsx的代码) 3. 数据与模板相结合,生成真实的DOM来显示 4. state发生改变 5. 数据与模板结合,生成真实DOM,替换原始的DOM 缺陷: 第一次生成了完整的DOM片段 第二次生成了完整的DOM片段 第二次的DOM替换第一次的DOM,非常耗性能
有时候我们只是改了页面上一小部分数据,这种方案下,却要替换整个DOM,性能很低。
方案二: 1. 定义一个state,先有数据 2. 有一个模板(render函数中jsx的代码) 3. 数据与模板相结合,生成真实的DOM来显示 4. state发生改变 5. 数据与模板结合,生成真实DOM,并不直接替换原始的DOM 6. 新的DOM(也就是DocumentFragment)和原始的DOM作比对,找差异 7. 找出input框发生了变化 8. 只用新的DOM中的input元素,替换掉旧的DOM中的input元素 缺陷: 虽然只替换发生了变化的input元素,提升了性能,但是在新旧DOM比对过程中也消耗了性能,因此性能提升的并不明显
方案三: 1. 定义一个state,先有数据 2. 有一个模板(render函数中jsx的代码) 3. 数据与模板相结合,生成真实的DOM来显示 例如真实的DOM:<div id='abc'><span>hello~</span></div> 4. 生成虚拟DOM 虚拟DOM:['div', {id:'abc'}, ['span', {}, 'hello~']] 5. state发生变化 6. 生成新的虚拟DOM 虚拟DOM:['div', {id:'abc'}, ['span', {}, 'bye~']] 7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容 8. 直接操作DOM,改变span中的内容 减少了真实DOM的创建以及对比,我们创建和对比的都是JS对象,这样提升了极大的性能。
实际上,react底层真正的实现:
1. 定义一个state,先有数据 2. 有一个模板(render函数中jsx的代码) 3. 生成虚拟DOM 虚拟DOM:['div', {id:'abc'}, ['span', {}, 'hello~']] 4. 用虚拟DOM的结构生成真实的DOM来显示 真实的DOM:<div id='abc'><span>hello~</span></div> 5. state发生变化 6. 生成新的虚拟DOM 虚拟DOM:['div', {id:'abc'}, ['span', {}, 'bye~']] 7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容 8. 直接操作DOM,改变span中的内容 当有了数据、JSX模板之后,react会先生成虚拟DOM,后依据虚拟DOM生成真实DOM。 JSX代码与真实的DOM之间的关系:先将JSX代码变成JS对象(react底层把JSX代码通过creatElement方法将其变成JS对象),再转化成真实的DOM
虚拟DOM的优点:
1. 提升了性能
2. 使得跨端应用得以实现。React Native