017.Diffing算法

一.验证Diffing算法存在

咱们建立一个定时器来维护state中的date,模拟每秒时间变化,同时放置一个输入框。这样状态是一直更新的,输入框是固定的DOM元素,咱们在输入框输入内容,若是状态更新时间变化,而输入框内的内容没有重置为空,说明有算法参与,识别input节点没有变化,则没有触发更新。react

image.png

class Time extends React.Component{
    state={
        date:new Date()
    }

    componentDidMount(){
        setInterval(()=>{
            this.setState({date : new Date()})
        },1000)
    }

    render(){
        return(
            <div> <h1>Hello</h1> <input type="text" /> <h2>如今是北京时间:{this.state.date.toTimeString()} <input type="text" /> </h2> 时间每隔一秒刷新一次 而h1和input标签不变化不从新渲染 因此在页面input中输入内容不被清空 </div>
        )
    }、
}
ReactDOM.render(<Time/>,document.getElementById('test'))
复制代码

结果很容易预测,input框内容确实不会被清空。
而代码中跟时间处于同一标签内的 ‘如今是北京时间:’也会跟着状态变化而更新
但h2标签中嵌套的input输入内容,依然不会更新
因此Diffing算法会逐层对比,最小粒度是标签(节点)算法

二.虚拟DOM中key的做用

举个栗子:数组

class Person extends React.Component{
    state={
        people:[
            {id:'1',name:'老秦',age:'22'},
            {id:'2',name:'小唐',age:'38'},
            {id:'3',name:'阿香',age:'27'},
        ]
    }

    componentDidMount(){
        setInterval(()=>{
            this.setState({date : new Date()})
        },1000)
    }
    add = () =>{
        const { people } = this.state
        const p = { id:people.length+1,name:'坤泰',age:39}
        this.setState({people:[p , ...people]})
    }

    render(){
        return(
            <div> <h2>展现人员信息</h2> <button onClick={this.add}>添加人员</button> <span>索引值做为key</span> <ul> { this.state.people.map((item,index)=>{ return( <li key={index}>{item.name}----{item.age}<input type="text"/></li> ) }) } </ul> <span>惟一标识做为key</span> <ul> { this.state.people.map((item)=>{ return( <li key={item.id}>{item.name}----{item.age}<input type="text"/></li> ) }) } </ul> </div>
        )
    }
}
ReactDOM.render(<Person/>,document.getElementById('test'))
复制代码

代码中对一组数据分别以索引值index做为key和惟一标识id做为key遍历生成具体DOM元素。
点击按钮在原数组前插入一条新的人员信息时,
索引值做为key:
建立虚拟DOM时,新插入的数据索引值index为0,原来的数据索引值依次加1,以此来建立虚拟DOM。 注意注意了兄弟萌,这时候Diffing算法过来跟这几条数听说把大家的key拿出来吧我瞅瞅,一看好家伙虚拟DOM的key跟原来真实DOM的key没一个同样的,你琢磨琢磨key都不同了,是不得把这些数据全得从新渲染成真实DOM。原本只要渲染新插入的一条,就由于你的蹩脚行为,致使如今三条都要从新渲染。
若是在你渲染数据时,顺手依据索引值渲染一个输入框输入各自对应的姓氏,index一旦变了全改姓了车祸现场
惟一标识做为key:
这就不用说了,key为惟一值不会变化很是稳健,渲染时比对直接渲染新增的key对应的DOM元素便可。markdown

image.png

总结:ui

1.虚拟DOM中key的做用:
 1).简单的说: key是虚拟DOM对象的标识,在更新显示时key起着极其重要的做用 2).详细的说:当状态中的数据发生变化时,react会根据【新数据】生成新的虚拟DOM 随后React进行了【新虚拟DOM】和【旧虚拟DOM】的比较,比较规则以下: a:旧虚拟DOM找到了与新虚拟DOM相同的key: (1).若虚拟DOM中内容没变,直接使用以前的真实DOM (2).若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中以前的真实DOM b:旧虚拟DOM中未找到与新虚拟DOM相同的key 根据数据建立新的真实DOM随后渲染到页面 
2.用index做为key可能会引起的问题:
 1).若对数据进行:逆序添加、逆序删除等破坏顺序的操做: 会产生没有必要的真实DOM更新 ===>界面效果没问题 但效率低 
 2).若是结构中还包含输入类的DOM 会产生错误的DOM更新 ===>界面有问题 
 3).注意:若是不存在对数据的逆序添加 逆序删除等破坏顺序的操做,仅用于渲染列表展现, 使用index做为key是没有问题的。 
3.开发中如何选择key
 1).最好每条数据的惟一标识做为key,好比id 2).若是只是简单的展现数据,index也能够 复制代码
相关文章
相关标签/搜索