React 中虚拟DOM的key
一、经典面试题
1、React 中虚拟DOM的key有什么作用?(key的内部原理是什么?)
2、为什么遍历列表时,key最好不要用index?
二、虚拟DOM中key的作用
当状态中的数据发生变化时,React会根据【新数据】生产【新的虚拟DOM】,然后React使用diff算法对比【新虚拟DOM】和【旧虚拟DOM】,规则如下:
1.【旧虚拟DOM】中找到了
与【新虚拟DOM】相同的key:
a.若虚拟DOM的内容没变
,直接使用之前的真实DOM
b.若虚拟DOM的内容变了
,则生产新的真实DOM,随后替换掉页面中之前真实DOM
2.【旧虚拟DOM】中未找到
与【新虚拟DOM】相同的key:
根据数据创建新的真实DOM,随后渲染到页面
三、用index作为key可能引发的问题
1、若对数据进行:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 页面效果没有问题,但效率低。
2、如果结构中包括输入类(input等)的DOM,会产生错误的DOM更新 ==>页面有问题
3、注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表的话,使用index作为key时没有问题的。
代码案例1:如果使用index作为key,实现逆序添加的需求—页面没有问题,但效率低
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例1-无输入类</title>
</head>
<body>
<!-- 创建一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom -->
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 引入bable,将jsx转化为js -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 表示写的是jsx -->
<script type="text/babel">
// 1.创建类式组件
class Demo extends React.Component {
state = {
person: [{
id: 1, name: '小张' }, {
id: 2, name: '小李' }] }
add = () => {
let {
person } = this.state;
let obj = {
id: 3,
name: '小王'
}
//逆序添加
person.unshift(obj);
this.setState({
person: person });
}
//render放在类的原型对象上
render() {
const {
person } = this.state;
return (
<div>
<h1>案例1-无输入类</h1>
<button onClick={
this.add}>逆序添加</button>
<ul>
{
person.map((item, index) => {
return <li key={
index}>{
item.id}{
item.name}</li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Demo id="id属性" />, document.querySelector('#test'));
</script>
</body>
</html>
代码案例2:如果使用index作为key,对含有输入类DOM的结构实现逆序添加的需求—页面有问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例2-有输入类</title>
</head>
<body>
<!-- 创建一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom -->
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 引入bable,将jsx转化为js -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 表示写的是jsx -->
<script type="text/babel">
// 1.创建类式组件
class Demo extends React.Component {
state = {
person: [{
id: 1, name: '小张' }, {
id: 2, name: '小李' }] }
add = () => {
let {
person } = this.state;
let obj = {
id: 3,
name: '小王'
}
//逆序添加
person.unshift(obj);
this.setState({
person: person });
}
//render放在类的原型对象上
render() {
const {
person } = this.state;
return (
<div>
<h1>案例2-有输入类</h1>
<button onClick={
this.add}>逆序添加</button>
<ul>
{
person.map((item, index) => {
return <li key={
index}>{
item.id}{
item.name} <input type="text"/></li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Demo id="id属性" />, document.querySelector('#test'));
</script>
</body>
</html>
输入框发生错乱,所以这里key肯定是要使用唯一标识
四、开发中如何选择key
1、最好使用每条数据的唯一标识作为key,比如id、手机号、身份证、学号等
2、如果确定只是简单的展示数据,用index也是可以的。
以上就是React 中虚拟DOM中key的内容,请大家关注《React 全家桶》专栏。
我会将自己平时项目中常见的问题以及笔试面试的知识在CSDN与大家分享,一起进步,加油。