(精华2020年5月28日更新) react基础篇 虚拟dom的渲染机制和性能调优

下面几种写法等同

//-------------------------1-----------------------------
    function Table ({rows}) {
        return (
            <table>
                {
                    rows.map(row=>(
                        <tr>
                            <td key={row.id}>{row.title}</td>    
                        </tr>
                    ))
                }    
            </table>
        )
    }
    <Table rows={rows}/>

    var rows = [{id:1,title:'第一的标题'}]

    ReactDOM.render(
        React.createElement(Table,{rows:rows}),
    
    document.getElementById('root'))

//-------------------------2-----------------------------
    var str = <div className="cn">
        content
    </div>
    var str = React.createElement('div',{className:'cn'},'content')
//-------------------------3-----------------------------
    {
        type:'div',
        props:{
            className:'cn',
            chilldren:[
                'content1'
            ]
        }
    }
//-------------------------4-----------------------------
    var com1 = <div className="cn" children={[<div>content1</div>,<p>content2</p>]}></div>

    
     ReactDOM.render(
        com1,
    
    document.getElementById('root'))

转换规则

// 1 如果type是一个string类型的标签名称 创建一个标签 附带上props下的所有attributes
    // 2 如果type是一个(function)(class) 调用它的时候 会对这个结果递归重复这个过程
    // 3 如果props下面有children属性 在父节点下重复以上的过程

更新规则

// render通常在根节点调用一次 后续的更新会有state来控制,要提高react性能从setstate下手
    // 在更新的时候 react将调用diff算法 
    // 场景1 type是一个字符串 type保持不变 props也保持不变
    // 更新前
    // {type:'div',props:{className:'cn'}}
    // 更新之后
    // {type:'div',props:{className:'cn'}} 这一种是最简单的情况 DOM保持不变

    // 场景2 type是一个字符串 type保持不变 props是不同的
    // 更新前
    // {type:'div',props:{className:'cn'}}
    // 更新之后
    // {type:'div',props:{className:'cnn'}}
    // 不会删除一个节点 而是直接改变props

    //  场景3 type已经改变成不同的string
    // 更新前
    // {type:'div',props:{className:'cn'}}
    // 更新之后
    // {type:'span',props:{className:'cn'}}
    
    // 甚至都不会尝试更新 直接删除掉 会删除掉所有的子节点 
    // 比较type 是通过 === 

    // 场景4 type是一个 component
    // 更新前
    // {type:Table,props:{rows}}
    // 更新后
    // {type:Table,props:{rows}}
    // 会对组件进行遍历和扫描 

组件的比较和生成详解

props:{
        children:[
            {type:'div',key:'div'},
            {type:'span',key:'span'},
            {type:'br',key:'br'}
        ]
    }

    props:{
        children:[
            {type:'span',key:'span'},
            {type:'br',key:'br'},
            {type:'div',key:'div'}
        ]
    }

    // 不含key的组件顺序不同会全部重新删除渲染
    // 一旦元素有一个key属性 将会按照key 而不是 index来比较 是要key是唯一的 react就会 移动元素
    // 而不是将他们直接删除 然后再生成

diff算法

+ domdiff算法解析
    + diff策略
        - dom节点跨层级的操作比较少
        - 拥有相同类的两个组件会生成相似的树形结构 不同的类组件会生成不同的树形结构
        - 同一层级的一组子节点 可以通过uuid进行区分
    + diff 粒度
        + tree diff 
            - 对树的每一层进行遍历 如果组件不存在了 会直接删除
        + Component diff
            - 同一类型的组件 继续比较下去 是否需要比较 -> shouldComponentUpdate
            - 不同类型的组件 直接替换
        + Element diff
            - 常见的类型就是列表
            - 比较策略就是 uuid 遍历一遍 确定要删除的和要更新的
            - uuid一般不要设置成数组的index

ReactElement 用来承载信息的容器 
1. type 类型 用于判断如何创建节点
2. key 和 ref 
3. props 新的属性内容
4. $$typeof 用于确定是否属于 ReactElement

删除主键性能调优


    <div>
        <Message />,    
        <Table />,    
        <Footer />,    
    </div>

    {
        props:{
            children:[
                {type:Message},
                {type:Table},
                {type:Footer},
            ]
        }
    }
    // 要把Message组件 删除掉  短路表达式is 

    // React.PureComponent  React.Component
    // 实施了一层浅的比较 shouldComponentUpdate 实施了一个浅的比较 
    // 浅的比较 props state 不是免费的 甚至于对大多数组件都是不值得的
    // 经验总结 : pureComponent 往往适用于 复杂的表单和表格 
    // 越简单越不建议使用pureComponent

高阶组件

export default High(Home)
const app=High(Home)
class Home extends React.Component{
  render(){
    return(
      // High(Home)  引用关系重新渲染不能在内部使用
      app
    )
  }
}

你可能感兴趣的:((持续更新)react基础篇)