经典面试题:
- react/vue中的key有什么作用?(key的内部原理是什么?)
- 为什么遍历列表时,key最好不要用index? 代码示范:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<div id="test"></div>
<script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component {
state = {persons: [{id: 1, name: '张三', age: 17}, {id: 2, name: '赵六', age: 18},]}
componentDidMount(){
setInterval(()=>{
this.setState({date: new Date()})
}, 1000)
}
addPerson = () => {
const {persons} = this.state
let visible = persons.length +1
this.setState({persons: [{id: visible, name: '路人甲'+ visible, age: visible}, ...persons]})
}
render() {
const {persons} = this.state
return (
<div>
<h1>人员列表</h1>
<button onClick={this.addPerson}>添加一个人</button>
<h5>使用index做key</h5>
{
persons.map((item, index)=> {
return <div key={index}>{item.name}-->{item.age}<input /></div>
})
}
<hr/>
<h5>使用唯一字段做key</h5>
{
persons.map((item, index)=> {
return <div key={item.id}>{item.name}-->{item.age}<input /></div>
})
}
</div>
);
}
}
ReactDOM.render(<Person/>, document.getElementById('test'))
</script>
</body>
</html>
代码运行后,向列表第一行位置添加一条人员信息,列表展示如下:
问题分析:
慢动作回放: --使用index作为key
初始化数据:
{id: 1, name: '张三', age: 17}
{id: 2, name: '赵六', age: 18}
初始化数据虚拟DOM:
<div key=0>张三-->17</div>
<div key=1>赵六-->18</div>
更新后的数据:
{id: 3, name: '路人甲', age: 19}
{id: 1, name: '张三', age: 17}
{id: 2, name: '赵六', age: 18}
更新后数据虚拟DOM:
<div key=0>路人甲-->19<input /></div> (转换真实DOM,input没有做更改)
<div key=1>张三-->17<input /></div> (转换真实DOM,input没有做更改)
<div key=2>赵六-->18<input /></div> (转换真实DOM,input是新转的DOM)
慢动作回放: --使用唯一标识作为key
初始化数据:
{id: 1, name: '张三', age: 17}
{id: 2, name: '赵六', age: 18}
初始化数据虚拟DOM:
<div key=1>张三-->17</div>
<div key=2>赵六-->18</div>
更新后的数据:
{id: 3, name: '路人甲', age: 19}
{id: 1, name: '张三', age: 17}
{id: 2, name: '赵六', age: 18}
更新后数据虚拟DOM:
<div key=3>路人甲-->19<input /></div> (转换真实DOM)
<div key=1>张三-->17<input /></div> (复用旧DOM)
<div key=2>赵六-->18<input /></div> (复用旧DOM)
总结
一. 虚拟DOM中key的作用
- 简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。
- 详细的说:当状态中的数据发生变化时,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是没问题的
三.开发中如果选择key
- 最好使用每条数据的唯一标识的key,如id、手机号、身份证号、学号等唯一值
- 如果确定只是简单的展示数据,用index也是可以的