React key值的作用和使用详解


Posted in Javascript onAugust 23, 2018

在react项目中总会遇到这样一个的坑

React key值的作用和使用详解

这是警告数组遍历子元素要有一个唯一的key值,但是key到底是什么,在代码中到底起了什么作用?

key概述

react中的key属性,它是一个特殊的属性,它的出现不是给开发者用的(例如你为一个组件设置key之后,也仍无法获取这个组件的key值),而是给react自己用的。

简单来说,react利用key来识别组件,它是一种身份标识标识,就像我们的身份证用来辨识一个人一样。每个key对应一个组件,相同的key react认为是同一个组件,这样后续相同的key对应组件都不会被创建。

key的使用场景

在项目开发中,key属性的使用场景最多的还是由数组动态创建的子组件的情况,需要为每个子组件添加唯一的key属性值。那会有的人就会自然而然想到,key和动态渲染的子元素获取的index位置的值很接近,那不是可以直接用index附上key的值呢key={index}?

例如:

{dataList.map((item,index)=>{
    return <div style={mystyle} key={index}>{item.name}</div>
    })
}

在你尝试过后会发现,报错没了,渲染也没问题不是很正常嘛?!但是强烈不推荐用数组index来作为key。
如果数据更新仅仅是数组重新排序或在其中间位置插入新元素,那么视图元素都将重新渲染。

例如:

本来index=2的元素向前移动后,那该元素的key不也同样发生了改变那这样会改变的Key就没有任何的存在意义,既然是作为“身份证”一样的存在,那就不容有失。当然,在你用key值创建子组件的时候,若数组的内容只是作为纯展示,而不涉及到数组的动态变更,其实是可以使用index作为key的。

key的值必须保证唯一且稳定

我在与Key值打过几次交道过后,觉得key值就类似于数据库中的主键id一样,有且唯一。

//this.state.users内容。注意:李四和王五的id相同!!!
this.state = {
 users: [{id:1,name: '张三'}, {id:2, name: '李四'}, {id: 2, name: "王五"}],
 ....//省略
}
render()
 return(
 <div>
  <h3>用户列表</h3>
  {this.state.users.map(u => <div key={u.id}>{u.id}:{u.name}</div>)}
 </div>
 )
);

注意以上范例中,动态渲染的数据中,key以数据的id来定,而李四、王五的id相同而导致Key的雷同,最后的渲染结果为张三和李四,王五并没有展示出来。主要是因为 react根据key认为李四和王五是同一个组件(李四和王五的key值相同),导致第一个被渲染,后续的会被丢弃掉。

这样,有了key属性后,就可以与组件建立了一种对应关系,react根据key来决定是销毁重新创建组件还是更新组件。

并且,Key也要保证值的稳定性,例如:

{dataList.map((item,index)=>{
    return <div style={mystyle} key={Math.random()}>{item.name}</div>
    })
}

尤其如以上范例中所示,key的值以Math.random()随机生成而定,这使得数组元素中的每项都重新销毁然后重新创建,有一定的性能开销;另外可能导致一些意想不到的问题出现。

所以,Key的值必须保证其唯一和稳定性

所以,在不能使用random随机生成key时,我们可以像下面这样用一个全局的localCounter变量来添加稳定唯一的key值。

var localCounter = 1;
this.data.forEach(el=>{
el.id = localCounter++;
});
//向数组中动态添加元素时,
function createUser(user) {
return {
...user,
id: localCounter++
}
}

key其它注意事项

当然除了为数据元素生成的组件要添加key,且key要稳定且唯一之外,还需要注意以下几点:

key属性是添加到自定义的子组件上,而不是子组件内部的顶层的组件上。

//MyComponent
...
render() {//error
<div key={{item.key}}>{{item.name}}</div>
}
...

//right
<MyComponent key={{item.key}}/>

key值的唯一是有范围的,即在数组生成的同级同类型的组件上要保持唯一,而不是所有组件的key都要保持唯一

不仅仅在数组生成组件上,其他地方也可以使用key,主要是react利用key来区分组件的,相同的key表示同一个组件,react不会重新销毁创建组件实例,只可能更新;key不同,react会销毁已有的组件实例,重新创建组件新的实例。

{
this.state.type ? 
<div><Son_1/><Son_2/></div>
: <div><Son_2/><Son_1/></div>
}

例如上面代码中,this.state.type的值改变时,原Son_1和Son2组件的实例都将会被销毁,并重新创建Son_1和Son_2组件新的实例,不能继承原来的状态,其实他们只是互换了位置。为了避免这种问题,我们可以给组件加上key。

{
this.state.type ? 
<div><Son_1 key="1"/><Son_2 key="2"/></div>
: <div><Son_2 key="2" /><Son_1 key="1"/></div>
}

这样,this.state.type的值改变时,Son_1和Son2组件的实例没有重新创建,react只是将他们互换位置。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
May 28 Javascript
详解JavaScript函数绑定
Aug 18 Javascript
js对字符的验证方法汇总
Feb 04 Javascript
三种AngularJS中获取数据源的方式
Feb 02 Javascript
Bootstrap基本样式学习笔记之标签(5)
Dec 07 Javascript
基于JavaScript实现滑动门效果
Mar 16 Javascript
深入理解vue-router之keep-alive
Aug 31 Javascript
JS处理一些简单计算题
Feb 24 Javascript
使用vue-cli(vue脚手架)快速搭建项目的方法
May 21 Javascript
Echarts地图添加引导线效果(labelLine)
Sep 30 Javascript
vue父子组件间引用之$parent、$children
May 20 Javascript
Vue select 绑定动态变量的实例讲解
Oct 22 Javascript
vue项目中使用lib-flexible解决移动端适配的问题解决
Aug 23 #Javascript
从零开始学习搭建React脚手架项目
Aug 23 #Javascript
angular2 ng2-file-upload上传示例代码
Aug 23 #Javascript
Angular angular-file-upload文件上传的示例代码
Aug 23 #Javascript
JS实现的简单分页功能示例
Aug 23 #Javascript
JavaScript实用代码小技巧
Aug 23 #Javascript
jQuery实现鼠标移到某个对象时弹出显示层功能
Aug 23 #jQuery
You might like
Mysql中limit的用法方法详解与注意事项
2008/04/19 PHP
php在window iis的莫名问题的测试方法
2013/05/14 PHP
php中让上传的文件大小在上传前就受限制的两种解决方法
2013/06/24 PHP
php实现字符串翻转的方法
2015/03/27 PHP
PHP chr()函数讲解
2019/02/11 PHP
Laravel框架控制器,视图及模型操作图文详解
2019/12/04 PHP
laravel框架中视图的基本使用方法分析
2019/11/23 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
Javascript 表单之间的数据传递代码
2008/12/04 Javascript
JavaScript 高级篇之闭包、模拟类,继承(五)
2012/04/07 Javascript
JS和函数式语言的三特性
2014/03/05 Javascript
Javascript学习笔记之 函数篇(二) : this 的工作机制
2014/06/24 Javascript
Javascript模拟加速运动与减速运动代码分享
2014/12/11 Javascript
一种新的javascript对象创建方式Object.create()
2015/12/28 Javascript
jQuery中的基本选择器用法学习教程
2016/04/14 Javascript
Javascript中获取浏览器类型和操作系统版本等客户端信息常用代码
2016/06/28 Javascript
vue checkbox 全选 数据的绑定及获取和计算方法
2018/02/09 Javascript
详解创建自定义的Angular Schematics
2018/06/06 Javascript
基于Vue实现的多条件筛选功能的详解(类似京东和淘宝功能)
2019/05/07 Javascript
在layui中对table中的数据进行判断(0、1)转换为提示信息的方法
2019/09/28 Javascript
Python网页解析利器BeautifulSoup安装使用介绍
2015/03/17 Python
Python实现提取XML内容并保存到Excel中的方法
2018/09/01 Python
Python小白必备的8个最常用的内置函数(推荐)
2019/04/03 Python
浅谈sklearn中predict与predict_proba区别
2020/06/28 Python
社区版pycharm创建django项目的方法(pycharm的newproject左侧没有项目选项)
2020/09/23 Python
OpenCV灰度化之后图片为绿色的解决
2020/12/01 Python
关于box-sizing的全面理解
2016/07/28 HTML / CSS
美国领先的奢侈手表在线零售商:WatchMaxx
2017/12/17 全球购物
限量版运动鞋和街头服饰:TheDrop
2020/09/06 全球购物
怎样有效的进行自我评价
2013/10/06 职场文书
《与朱元思书》的教学反思
2014/04/17 职场文书
爱国演讲稿400字
2014/05/07 职场文书
北大自主招生自荐信
2015/03/04 职场文书
人民检察院起诉书
2015/05/20 职场文书
SpringBoot连接MySQL获取数据写后端接口的操作方法
2021/11/02 MySQL
详解flex:1什么意思
2022/07/23 HTML / CSS