美文网首页
React学习笔记(二)

React学习笔记(二)

作者: 滨滨_57b5 | 来源:发表于2019-01-09 14:26 被阅读0次

    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方法是异步执行的)

    问题:为什么setState方法会被React设计成一个异步方法?
    场景:如果在很短时间间隔内,连续调用了3次setState方法,那么React底层可能会调用3次Diff算法进行比对,这样会很消耗性能
    React实现:会将这3次调用setState方法合并为只调用一次setState方法,即只做一次虚拟DOM的比对,然后更新一次DOM

    1547014058427.jpg
    • Diff算法会按照同层比较的方式进行比对
    • 如果第一层进行比对时就不一样,React就不会继续往下一层比对了,它会将原始的虚拟DOM下的节点全部删除,然后用重新生成节点下的虚拟DOM替换原始的虚拟DOM下的所有节点
    1547014477063.jpg
    • 在虚拟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算法的一部分

    相关文章

      网友评论

          本文标题:React学习笔记(二)

          本文链接:https://www.haomeiwen.com/subject/sxjwrqtx.html