前置知识
Diffing算法:
- 每次做比较的时候最小的“粒度”是标签(节点);
- Diffing算法进行对比时是嵌套的;
虚拟DOM中key的作用:
1). 简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。
2). 详细的说:当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较:比较规则如下:
a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
(1). 若虚拟DOM中内容没变,直接使用之前的真实DOM
(2). 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
b. 旧虚拟DOM中未找到与新虚拟DOM相同的key,则根据数据创建的新的真实DOM,随后渲染到页面。
用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 页面效果没问题,但效率低,若数据量过大,则会造成页面卡顿、响应慢。
- 如果结构中还包含输入类的DOM:会产生错误的DOM更新 ===> 页面有问题。
- 如果仅是用于渲染列表展示,则可以使用index作为key。
下面来看一段代码示例:
state = {
persons: [
{id: 1, name: '小张', age: 18},
{id: 2, name: '小李', age: 19},
]
}
add = () => {
const { persons } = this.state;
const p = { id: persons.length + 1, name: '小王', age: 20 };
this.setState({
persons: [p, ...persons],
});
}
render() {
return (
<>
<button onClick={this.add}>添加一个小王</button>
<ul>
{
this.state.persons.map((ele, index) => {
return <div style={{ display: 'flex' }}><li key={index}>{ele.name}---{ele.age}</li><input /></div>
})
}
</ul>
</>
)
}
正是因为将 key设置为index,导致出现了错误的DOM更新。