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

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

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

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

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

渲染多个组件

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

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

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

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

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

在CodePen里试一试

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

基础列表组件

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

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

  1. function NumberList(props) {
  2. const numbers = props.numbers;
  3. const listItems = numbers.map((number) =>
  4. <li>{number}</li>
  5. );
  6. return (
  7. <ul>{listItems}</ul>
  8. );
  9. }
  10.  
  11. const numbers = [1, 2, 3, 4, 5];
  12. ReactDOM.render(
  13. <NumberList numbers={numbers} />,
  14. document.getElementById('root')
  15. );

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

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

  1. function NumberList(props) {
  2. const numbers = props.numbers;
  3. const listItems = numbers.map((number) =>
  4. <li key={number.toString()}>
  5. {number}
  6. </li>
  7. );
  8. return (
  9. <ul>{listItems}</ul>
  10. );
  11. }
  12.  
  13. const numbers = [1, 2, 3, 4, 5];
  14. ReactDOM.render(
  15. <NumberList numbers={numbers} />,
  16. document.getElementById('root')
  17. );

在CodePen里试一试

keys

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

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

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

  1. const todoItems = todos.map((todo) =>
  2. <li key={todo.id}>
  3. {todo.text}
  4. </li>
  5. );

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

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

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

依据key提取组件

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

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

例子:错误的用法

  1. function ListItem(props) {
  2. const value = props.value;
  3. return (
  4. // Wrong! There is no need to specify the key here:
  5. <li key={value.toString()}>
  6. {value}
  7. </li>
  8. );
  9. }
  10.  
  11. function NumberList(props) {
  12. const numbers = props.numbers;
  13. const listItems = numbers.map((number) =>
  14. // Wrong! The key should have been specified here:
  15. <ListItem value={number} />
  16. );
  17. return (
  18. <ul>
  19. {listItems}
  20. </ul>
  21. );
  22. }
  23.  
  24. const numbers = [1, 2, 3, 4, 5];
  25. ReactDOM.render(
  26. <NumberList numbers={numbers} />,
  27. document.getElementById('root')
  28. );

例子:正确的用法

  1. function ListItem(props) {
  2. // Correct! There is no need to specify the key here:
  3. return <li>{props.value}</li>;
  4. }
  5.  
  6. function NumberList(props) {
  7. const numbers = props.numbers;
  8. const listItems = numbers.map((number) =>
  9. // Correct! Key should be specified inside the array.
  10. <ListItem key={number.toString()}
  11. value={number} />
  12. );
  13. return (
  14. <ul>
  15. {listItems}
  16. </ul>
  17. );
  18. }
  19.  
  20. const numbers = [1, 2, 3, 4, 5];
  21. ReactDOM.render(
  22. <NumberList numbers={numbers} />,
  23. document.getElementById('root')
  24. );

在CodePen里试一试

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

key必须唯一

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

  1. function Blog(props) {
  2. const sidebar = (
  3. <ul>
  4. {props.posts.map((post) =>
  5. <li key={post.id}>
  6. {post.title}
  7. </li>
  8. )}
  9. </ul>
  10. );
  11. const content = props.posts.map((post) =>
  12. <div key={post.id}>
  13. <h3>{post.title}</h3>
  14. <p>{post.content}</p>
  15. </div>
  16. );
  17. return (
  18. <div>
  19. {sidebar}
  20. <hr />
  21. {content}
  22. </div>
  23. );
  24. }
  25.  
  26. const posts = [
  27. {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
  28. {id: 2, title: 'Installation', content: 'You can install React from npm.'}
  29. ];
  30. ReactDOM.render(
  31. <Blog posts={posts} />,
  32. document.getElementById('root')
  33. );

在CodePen里试一试

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

  1. const content = posts.map((post) =>
  2. <Post
  3. key={post.id}
  4. id={post.id}
  5. title={post.title} />
  6. );

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

在JSX中嵌入map()

 在之前的例子里我们在JSX里声明了单独的listItems变量:
  1. function NumberList(props) {
  2. const numbers = props.numbers;
  3. const listItems = numbers.map((number) =>
  4. <ListItem key={number.toString()}
  5. value={number} />
  6. );
  7. return (
  8. <ul>
  9. {listItems}
  10. </ul>
  11. );
  12. }

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

  1. function NumberList(props) {
  2. const numbers = props.numbers;
  3. return (
  4. <ul>
  5. {numbers.map((number) =>
  6. <ListItem key={number.toString()}
  7. value={number} />
  8. )}
  9. </ul>
  10. );
  11. }
有些时候这样写可以让你的代码更清晰,但是这个风格也能被滥用。就像在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. asp.net mvc 简单实现一个账号只能在一个地方登录

    原理:  假设用户在机器A登陆后,  这时用户再次在机器B登陆,会以当前会话的SessionID作为键,用户id作为值,插入dictionary集合中,集合再保存在application(保存在服务器 ...

  2. NIO学习资料

    五大IO模型 https://jiges.github.io/2018/02/07/%E4%BA%94%E5%A4%A7IO%E6%A8%A1%E5%9E%8B/ Getting started wi ...

  3. ajax 显示,删除,批量删除,修改反填功能实现

    1.页面代码 <body> <h1>显示所有员工信息</h1> <input id="Button1" type="button ...

  4. word之高级

    1.更正拼写和语法错误. 2.取消自动编号. 3.添加删除水印. 4.段落设置首行缩进2个字符. 需要先选中需要设置的段落 5.文字覆盖. insert键切换插入与改写功能.修改word状态栏上的改写 ...

  5. KVM 通过virsh console连入虚拟机

    新安装一台虚拟机后,是无法通过virsh console 命令连入虚拟机中的,这时我们需要开启虚拟机的console功能. 一.添加ttyS0的许可,允许root登陆 [root@localhost ...

  6. Twisted简介

    Twisted是用Python实现的基于事件驱动的网络引擎框架,Twisted支持许多常见的传输及应用层协议,包括TCP.UDP.SSL/TLS.HTTP.IMAP.SSH.IRC以及FTP.就像Py ...

  7. java微信开发之地图定位

    页面代码: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnc ...

  8. LeetCode #002# Add Two Numbers(js描述)

    索引 思路1:基本加法规则 思路2:移花接木法... 问题描述:https://leetcode.com/problems/add-two-numbers/ 思路1:基本加法规则 根据小学学的基本加法 ...

  9. PHP防止网页快速刷新+代理ip访问

    前几天网站收到了一些CC攻击,比较郁闷...这里分享一下,防止网页自动刷新的方法以及阻止代理IP访问网站的方法,代码是分开的,两个功能,需要那个用那个,可以自定义时间间隔,这个代码不止可以防CC攻击, ...

  10. java web 的 几种跨域方式