使用React.Children.map()
函数
const App = (props) => {
return (
<ul>
{a.map(i => {
return <li key={i}>{i}</li>
})}
</ul>
)
}
使用下方写法,效果与上放写法效果相同,写法简单
const App = (props) => {
return (
<ul>
{React.Children.map(a, i => <li>{i}</li>)}
</ul>
)
}
在React.Children
我们可用的对象中还有其他几种非常有用的方法。我们将主要使用该React.Children.map()
功能,但了解其他可用的功能是很好的。查看文档以获取更长的列表。
这篇文章是30天React系列的一部分 。
在本系列中,我们将从非常基础开始,逐步了解您需要了解的所有内容,以便开始使用React。如果您曾经想学习React,那么这里就是您的最佳选择!
重复元素
今天我们将研究如何显示多个组件,以准备将外部数据导入我们的应用程序。
到目前为止,我们一直在构建一个没有任何外部数据的基本应用程序。在我们到达那里之前(明天我们将开始使用此功能),让我们看一下前两周我们掩盖的内容:
重复元素
在我们迭代一个对象列表并在屏幕上渲染多个组件之前,我们已经看到了这一点。在我们通过加载外部数据在我们的应用程序中添加太多复杂性之前,今天我们将快速查看如何在我们的应用程序中重复组件/元素。
由于JSX被浏览器视为普通JavaScript,因此我们可以在JSX中使用模板标签内的任何ole'JavaScript。我们已经看到了这一点。作为快速演示:
const a = [10,100];
const App = (props) => {
return (
<ul>
{a.map(i => {
return <li>{i}</li>
})}
</ul>
)
}
请注意,模板标签内部的内容{}
看起来就像简单的JavaScript。那是因为它只是JavaScript。此功能允许我们在模板标记内部使用(大多数)JavaScript的本机功能,包括本机迭代器,例如map
和forEach
。
让我们看看我们在这里的含义。让我们将前一个示例的a
值从单个整数转换为整数列表:
const a = [1, 10, 100, 1000, 10000];
我们可以a
在组件内部映射变量,并返回将为我们构建虚拟DOM的React组件列表。
const App = (props) => {
return (
<ul>
{a.map(i => {
return <li>{i}</li>
})}
</ul>
)
}
功能是什么
map()
?该
map
函数是数组上的本机JavaScript内置函数。它接受一个在数组的每个元素上运行的函数,因此上面的函数将以i
start为值运行四次1
,然后它将再次运行它为第二个值i
设置为as10
等等等等向前。
让我们在App
这里使用我们的组件更新我们在第12天创建的应用程序。让我们打开我们的src/App.js
文件,App
用这个源代替组件的内容。清理一些未使用的变量,你src/App.js
应该看起来像这样:
import React from 'react';
const a = [1, 10, 100, 1000, 10000];
const App = (props) => {
return (
<ul>
{a.map(i => {
return <li>{i}</li>
})}
</ul>
)
}
export default App
使用命令生成的create-react-app
命令再次启动应用程序:npm start
,我们可以看到应用程序正在浏览器中运行!
但是,如果我们打开开发者控制台,我们会看到打印出错误。这个错误是由于React不知道如何跟踪列表中的各个组件这一事实,因为每个<li />
组件看起来都像一个组件。
出于性能原因,React使用虚拟DOM来尝试限制重新呈现视图时需要更新的DOM元素的数量。也就是说,如果没有任何改变,React将不会让浏览器更新任何东西以节省工作。
此功能对于构建Web应用程序非常有用,但有时我们必须通过为节点提供唯一标识符来帮助React。映射列表并在地图中渲染组件就是其中之一。
React希望我们通过使用特殊的prop 来唯一地标识组件:key
列表中每个元素的prop。该key
道具可以是任何东西,我们想要的,但它必须是唯一的该元素。在我们的示例中,我们可以i
在映射中使用该变量,因为数组中没有其他元素具有相同的值。
让我们更新我们的映射来设置密钥:
const App = (props) => {
return (
<ul>
{a.map(i => {
return <li key={i}>{i}</li>
})}
</ul>
)
}
孩子
我们本周早些时候讨论了建立亲子关系的问题,但让我们更详细地了解一下我们如何访问父组件内的子项以及如何呈现它们。
在第11天,我们构建了一个<Formatter />
组件来处理Clock组件中的日期格式,以便为用户提供自定义时钟渲染的灵活性。回想一下,我们创建的实现实际上非常丑陋且相对复杂。
const Formatter = (props) => {
let children = props.format.split('').map((e, idx) => {
if (e === 'h') {
return <Hour key={idx} {...props} />
} else if (e === 'm') {
return <Minute key={idx} {...props} />
} else if (e === 's') {
return <Second key={idx} {...props} />
} else if (e === 'p') {
return <Ampm key={idx} {...props} />
} else if (e === ' ') {
return <span key={idx}> </span>;
} else {
return <Separator key={idx} {...props} />
}
});
return <span>{children}</span>;
}
我们可以使用该React.Children
对象映射React对象列表,并让React做这个繁重的工作。结果是一个更清洁的Formatter
组件(不完美,但功能):
const Formatter = ({format, state}) => {
let children = format.split('').map(e => {
if (e == 'h') {
return <Hour />
} else if (e == 'm') {
return <Minute />
} else if (e == 's') {
return <Second />
} else if (e == 'p') {
return <Ampm />
} else if (e == ' ') {
return <span> </span>;
} else {
return <Separator />
}
});
return (<span>
{React.Children
.map(children, c => React.cloneElement(c, state))}
</span>)
}
React.cloneElement
我们还没有讨论这个
React.cloneElement()
功能,所以我们在这里简要介绍一下。记得WWWWWAAAAAYYYYY回到第2天我们看了浏览器如何看待 JSX?它将其转换为类似于以下内容的JavaScript:React.createElement("div", null, React.createElement("img", {src: "profile.jpg", alt: "Profile photo"}), React.createElement("h1", null, "Welcome back Ari") );
我们不是创建一个新的组件实例(如果我们已经有一个),有时我们会想要复制它或将自定义道具/子项添加到组件中,这样我们就可以保留它创建的相同道具。我们可以用它
React.cloneElement()
来处理这个问题。它与参数所在的函数
React.cloneElement()
具有相同的APIReact.createElement()
:
- 我们要克隆的ReactElement
- 任何
props
我们要添加到该实例children
我们想要的任何东西。在我们的
Formatter
例子中,我们创建所有的孩子列表中的一个副本(<Hour />
,<Minute />
,等部件),并通过他们的state
对象作为自己的道具。
该React.Children
对象提供了一些很好的实用功能来处理孩子。我们Formatter
上面的示例使用该map
函数迭代子节点并克隆列表中的每个子节点。它key
为每一个创造了一个(如果必要的话),使我们不必自己管理唯一性。
让我们使用该React.Children.map()
函数来更新我们的App组件:
const App = (props) => {
return (
<ul>
{React.Children.map(a, i => <li>{i}</li>)}
</ul>
)
}
回到浏览器,一切仍然有效。
在React.Children
我们可用的对象中还有其他几种非常有用的方法。我们将主要使用该React.Children.map()
功能,但了解其他可用的功能是很好的。查看文档以获取更长的列表。
截至通过这一点,我们只处理本地数据,没有真正专注于远程数据(虽然我们没有建立我们的活动饲料成分时,简单地提到它)。明天我们将开始与服务器进行交互,以便我们可以在我们的React应用程序中使用它。
今天干得好!
学习REACT正确的方法
React和朋友的最新,深入,完整的指南。
下一章:
获取远程数据
本教程系列的完整源代码可以在GitHub repo上找到,其中包括所有样式和代码示例。
如果您在任何时候感到困难,还有其他问题,请随时通过以下方式与我们联系:
- 在文章末尾评论这篇文章
- 通过react@fullstackreact.com发送电子邮件给我们
- 加入我们的gitter室
- 发送电子邮件至@fullstackreact