state, props,render()
为什么说React是由数据驱动的?
- 当组件的state或者props发生改变时,render函数就会被执行,而页面又是由render函数渲染出来的,因此说,数据一旦改变页面就会随之改变
- 当父组件的render函数被执行时,它的子组件的render函数也会被执行一次
虚拟DOM
React中的render()函数执行效率是非常高的,原因在于React中使用了虚拟DOM
- 原因:减少了JS中创建真实DOM的性能损耗,取而代之的是创建虚拟DOM,就是JS对象,另外在进行对比时减去了真实DOM的对比,取而代之的是虚拟DOM即JS对象的对比,从而提高了性能
1 生成state数据
2 JSX模版
3 生成虚拟DOM(虚拟DOM就是一个JS数组对象,用它来描述真实DOM) --此处会带来一些新能损耗,但是JS生成一个对象性能损耗是很小的,如果用JS生成一个DOM,会使用webApplication的API,这种性能损耗是很大的
['div', {id: 'abc'}, ['span',{ }, 'hello world']]
4 用虚拟DOM生成真实的DOM,来显示
<div id='abc'><span>hello world</span></div>
5 state 发生变化
6 数据 + 模版 生成新的虚拟DOM
['div', {id: 'abc'}, ['span',{ }, 'bye bye']]
7 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容
8 直接操作DOM 改变span中的内容
JSX模版生成真实DOM流程
- JSX代码就是一个模版,并不是真实的DOM,之后React会将模版与state结合,最终生成一个虚拟DOM即JS对象,之后才会生成真实DOM
- jSX -> JS对象 -> 真实DOM
JSX底层如何被转为JS对象?最终又是如何变为真实DOM?
- 使用了
React.createElement('div',{属性},'item')
,将一个对象传给createElement函数,函数内部首先会生成一个虚拟DOM,最终渲染成真实的DOM- jSX -> createElement函数 -> 虚拟DOM(JS对象) -> 真实DOM
虚拟DOM的优点
- 提升了性能
- 得以实现跨端应用(例如RN,得益于虚拟DOM才能实现原生应用,因为如果没有虚拟DOM,当使用JSX模版和数据结合后去直接渲染真实DOM,在浏览器中是没有问题的,在手机端是不存在DOM这个概念的,因此手机端是无法使用的;当使用了虚拟DOM后,JS对象是可以被手机端识别的,在PC端最终会生成真实DOM,在手机端不会生成真实的DOM,而是生成一些原生的组件)
虚拟DOM中的Diff(Difference)算法
此算法针对上述步骤中的第7步,即比较原始虚拟DOM和新的虚拟DOM的区别,可以提高比对性能
- React底层在调用了
setState
方法时,才会出发Diff算法(setState
方法是异步执行的)
1547014058427.jpg问题:为什么
setState
方法会被React设计成一个异步方法?
场景:如果在很短时间间隔内,连续调用了3次setState
方法,那么React底层可能会调用3次Diff算法进行比对,这样会很消耗性能
React实现:会将这3次调用setState
方法合并为只调用一次setState
方法,即只做一次虚拟DOM的比对,然后更新一次DOM
- Diff算法会按照同层比较的方式进行比对
- 如果第一层进行比对时就不一样,React就不会继续往下一层比对了,它会将原始的虚拟DOM下的节点全部删除,然后用重新生成节点下的虚拟DOM替换原始的虚拟DOM下的所有节点
- 在虚拟DOM比对时,每个节点都会有一个key值,这样便于与新的虚拟DOM进行比对
- 也是为什么在做循环操作时,不要省略key值,这样就无法保证在原始虚拟DOM中的key值与新的虚拟DOM的key值保持一致
- 例如在如下循环中,使用了index作为key值时,此时输入a,b,c
a 对应key值为0 b对应key值为1 c对应key值为2
当删除a时,此时 b对应key值为0 ,c对应key值为1
那么此时,b之前的key值是1,当前b的key值是0 ,所以就没有办法建立起关系了
这就是用index作为key值的一个问题,会导致key值不稳定
return this.state.list.map((item,index) => {
return (
<div key={index}>
<TodoItem
textContent={item}
index={index}
deleteItem={this.handleItemDelete}
/>
</div>
)
})
总结: 同层比较和key值比较都是diff算法的一部分
网友评论