首先,我们回顾一下在js里如何转换数组。

给出下面的代码,我们使用map()函数来获取一个数组的numbers然后将值变成两倍大。我们分配新数组由map()返回:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);

这段代码在控制台输出[2, 4, 6, 8 ,10]。

在React里,把数组转变成一系列元素也是一样的。

渲染多个组件

通过使用花括号,你可以创建一组元素,并且把它们包含在JSX里。

下面,我们对numbers数组使用map()函数。为每一项返回一个<li>元素。最后,我们将元素数组处理的结果存为listItems:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);

我们将整个listItems数组放进一个<ul>元素里,然后把它渲染到DOM里:

ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);

在CodePen里试一试

这段代码展示了一个1到5的数字列表。

基础列表组件

通常你会将列表渲染到一个组件里。

我们可以重构上一个例子到一个组件里,这个组件接受一个number数组,输出一个无序的元素列表。

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
} const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);

当你运行这段代码 ,你会看到一个警告,一个key需要提供给列表。“key”是一个特殊的字符串属性当你创建列表元素的时候你所需要的属性。在下一章节会讨论为什么这个属性很重要。

让我们在numbers.map()里分配一个key给列表元素来修复没有key的问题。

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
} const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);

在CodePen里试一试

keys

key帮助React鉴别哪一项发生了改变,添加了,或者移除了。key应该添加在数组里的元素身上作为一个稳定的特性。(我靠,这个是不是和html里的自定义属性很像啊)

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);

key最好的方式是用一个字符串唯一地标识一个列表的项。多数情况你会使用数据的ID来作为key:

const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);

当你的数据没有稳定的ID,也许会用数据项的索引作为key:

const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);

如果数据项可以重排序我们不建议使用索引作为key,因为那样会降低速度。也许你可以读一读这篇深入理解为何key很重要

依据key提取组件

元素的key只有在它和它的兄弟节点对比时才有意义。

举个例子,如果你提取了一个ListItem组件,你应该保持key在数组里的<listItem />元素里而不是在ListItem的<li>元素里。

例子:错误的用法

function ListItem(props) {
const value = props.value;
return (
// Wrong! There is no need to specify the key here:
<li key={value.toString()}>
{value}
</li>
);
} function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Wrong! The key should have been specified here:
<ListItem value={number} />
);
return (
<ul>
{listItems}
</ul>
);
} const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);

例子:正确的用法

function ListItem(props) {
// Correct! There is no need to specify the key here:
return <li>{props.value}</li>;
} function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Correct! Key should be specified inside the array.
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
} const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);

在CodePen里试一试

好的做法就是在map()方法调用里面的元素需要key。

key必须唯一

key跟兄弟节点比较的时候必须唯一。然而不需要全局唯一。当我们创建两个数组的时候可以出现相同的key。

function Blog(props) {
const sidebar = (
<ul>
{props.posts.map((post) =>
<li key={post.id}>
{post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) =>
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar}
<hr />
{content}
</div>
);
} const posts = [
{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
ReactDOM.render(
<Blog posts={posts} />,
document.getElementById('root')
);

在CodePen里试一试

key对React来说就是一个提示但是它们没有传递给你的组件。如果你需要同样的值在你的组件里,那就换一个不同的名字把它作为props传递:

const content = posts.map((post) =>
<Post
key={post.id}
id={post.id}
title={post.title} />
);

通过上面的例子,Post组件可以读取props.id这个属性,而不是props.key。

在JSX中嵌入map()

 在之前的例子里我们在JSX里声明了单独的listItems变量:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}

JSX允许嵌入任何表达式在花括号里因此我们能够内嵌map()直接到ul里面:

function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
有些时候这样写可以让你的代码更清晰,但是这个风格也能被滥用。就像在js里,决定是否有必要提取一个变量这取决于你。记住如果map()嵌套太深,也许是时候该提取一个组件了。

React文档(九)list和key的更多相关文章

  1. React文档(十三)思考React

    在我们的看来,React是使用js创建大型快速网站应用的首要方法.它在Facebook和Instagram的使用已经为我们展现了它自己. React的一个很好的地方就在于当你创建应用的时候它使你思考如 ...

  2. React文档(二十四)高阶组件

    高阶组件(HOC)是React里的高级技术为了应对重用组件的逻辑.HOCs本质上不是React API的一部分.它是从React的组合性质中显露出来的模式. 具体来说,一个高阶组件就是一个获取一个组件 ...

  3. react文档demo实现输入展示搜索结果列表

    文档页面地址:https://doc.react-china.org/docs/thinking-in-react.html 该文档只给了具体实现思路,下面是我实现的代码. 初学react,如果有写的 ...

  4. CYQ.Data 轻量数据层之路 优雅V1.4 现世 附API帮助文档(九)

    继上一版本V1.3版本发布到现在,时隔N天了:[V1.3版本开源见:CYQ.Data 轻量数据层之路 华丽V1.3版本 框架开源] N天的时间,根据各路网友的反映及自身的想法,继续修改优化着本框架,力 ...

  5. React文档(一)安装

    React是一个灵活的可以用于各种不同项目的框架,你可以用它来写新应用,你也可以逐步将它引进已有的代码库而不用重写整个项目. 试用React 如果你想玩一玩React,那么就去CodePen上试一试. ...

  6. React文档(十九)不使用ES6

    通常你会将一个React组件定义成一个普通的js类: class Greeting extends React.Component { render() { return <h1>Hell ...

  7. React文档(二十一)协调

    React提供了一个声明式地API因此你不用担心每一次更新什么东西改变了.这使得开发应用变得简单,但是这个东西在React中如何实现的并不是很明显.这篇文章会解释我们在React的算法中所做的选择以便 ...

  8. React文档(十六)refs和DOM

    Refs 提供了一种方式,用于访问在 render 方法中创建的 DOM 节点或 React 元素. 在标准的React数据流中,props是使得父组件和子组件之间交互的唯一方式.你通过props重新 ...

  9. React文档(十五)使用propTypes进行类型检查

    注意: React.PropTypes 自 React v15.5 起已弃用.请使用 prop-types 库代替. 随着你的应用的开发,你会使用类型检查的方法来捕获很多bug.对于一些应用,你可以使 ...

随机推荐

  1. 代码中特殊的注释技术——TODO、FIXME和XXX的用处(转)

    1.声明 本篇转自博客:http://blog.csdn.net/reille/ 2.转载内容 2.1.前言 今天在阅读 Qt Creator 的源代码时,发现一些注释中有 FIXME 英文单词,用英 ...

  2. Cutterman - 最好用的切图工具

    Cutterman - 最好用的切图工具 http://www.cutterman.cn/zh/cutterman

  3. OfficeOpenXml:World、Excel导出导入库

    基础库:EPPlus 根据模版:OfficeOpenXml.Entends

  4. ubuntu常用软件命令

    解压zip软件 unzip  xxx.zip -d解压到指定目录 清理磁盘空间 sudo apt-get autoremove sudo apt-get clean sudo dpkg --list ...

  5. cocos2dx JS layuot纯代码实现背景颜色渐变

    // view._partyBtnClassify.setBackGroundColorType(ccui.Layout.BG_COLOR_GRADIENT);// view._partyBtnCla ...

  6. 57.搭建Vue环境

    nodejs官网http://nodejs.cn/下载安装包,无特殊要求可本地傻瓜式安装,这里选择2017-5-2发布的 v6.10.3 cmd命令行: node -v //显示node版本 v6.1 ...

  7. fiddler学习总结--fiddler抓包篡改数据请求

    操作步骤: 步骤一.在fiddler的命令行中输入需要拦截的地址:bpu https://www.baidu.com 记得按一下回车键 步骤二.在百度搜索栏中,输入“火影忍者”,页面会一直处于加载的状 ...

  8. Java代码走查具体考察点

    代码走查具体考察点 一.参数检验 公共方法都要做参数的校验,参数校验不通过,需要明确抛出异常或对应响应码. 在接口中也明确使用验证注解修饰参数和返回值,作为一种协议要求调用方按注解约束传参,返回值验证 ...

  9. percona-toolkit工具的使用

    percona-toolkit是一组高级命令行工具的集合,可以查看当前服务的摘要信息,磁盘检测,分析慢查询日志,查找重复索引,实现表同步等等 percona-toolkit 源自 Maatkit 和 ...

  10. function的toString方法

    javascript的创建多行字符串的除了平时常见的”“+ 反斜杠\ 还有ES6的` ` 在js51上发现一个很有意思的方法 function heredoc(fn) { return fn.toSt ...