React教程: 第13天 重复元素

本文转载自:众成翻译
译者:iOSDevLog
链接:https://www.zcfy.cc/article/3826
原文:https://www.fullstackreact.com/30-days-of-react/day-13/

这篇文章是30 Days of React系列的一部分。
在本系列中,我们将从最基本的开始,逐步了解开始React所需的所有知识。如果你曾经想学习反应,这是开始的地方!

30 Days of React PDF版本下载:下载超过300页的 PDF

今天,我们将通过如何显示多个组件来准备将外部数据引入我们的应用。

我们已经构建了一个没有任何外部数据的基本应用。在我们实现之前 (我们将在明天开始这个功能), 让我们来看看过去两周中我们所掩盖的事情:

Repeating elements(重复元素)


我们已经看到了这之前, 我们已经遍历了一个对象列表, 并在屏幕上呈现多个组件。在我们的应用中添加太多的复杂度来加载外部数据之前, 今天我们将快速了解如何在应用中重复组件/元素。

由于JSX被浏览器视为纯 javascript 的, 我们可以使用任何传统 javascript 内的模板标签中的JSX。我们已经看到了这一行动。作为一个快速演示:

const a = 10;
const ShowA = () => <div>{a}</div>;
const MultipleA = () => <div>{a * a}</div>;

const App = props => {
  return (
    <div className="app">
      <ShowA />
      <MultipleA />
    </div>
  );
};

在这里插入图片描述

注意模板标签{} 内的内容看起来简单的 javascript。那是因为它 只是 javascript。此功能允许我们使用 (大多数) 的 javascript 在我们的模板标签包括原生迭代器, 如 mapforEach

让我们来看看这是什么意思。让我们将上一个示例的 a 值从单个整数转换为整数列表:

const a = [1, 10, 100, 1000, 10000];

我们可以将 a 变量映射到我们的组件中, 并返回将为我们构建虚拟 DOM 的响应组件列表。

const a = [1, 10, 100, 1000, 10000];
const Repeater = () => {
  return (
    <ul>
      {a.map(i => {
        return <li>{i}</li>;
      })}
    </ul>
  );
};

什么是map() 函数?

map() 函数是数组中一个原生javascript内置函数的。 它接受在数组的每个元素上运行的函数, 因此, 上面的函数将运行四次, 其值为i开始为1, 然后它将再次运行它的第二个值, i将被设置为10等等等等。
React教程: 第13天 重复元素_第1张图片
让我们更新我们在第12天创建的应用与我们的 App组件在这里。让我们打开我们的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教程: 第13天 重复元素_第2张图片
但是, 如果我们打开开发人员控制台, 我们将看到打印出错误。此错误是由以下事实引起的: React不知道如何跟踪我们列表中的各个组件, 因为它们只是看起来像一个

  • 组件。

    出于性能原因, React使用虚拟 DOM 尝试限制在重新视图时需要更新的 DOM 元素的数量。如果没有任何变化, React不会使浏览器更新任何东西以节省工作。

    此功能非常适合于构建 web 应用, 但有时我们必须通过为节点提供唯一标识符来帮助做出React。在映射列表和渲染组件是其中之一。

    React要求我们通过使用特殊属性来识别惟一的组件, 这是列表中每个元素的 key属性。key 属性可以是任何我们想要的, 但它 必须是唯一的 的元素。在我们的示例中, 我们可以在 map 中使用i变量, 因为数组中没有其他元素具有相同的值。

    让我们更新映射来设置key:

    const App = props => {
      return (
        <ul>
          {a.map(i => {
            return <li key={i}>{i}</li>;
          })}
        </ul>
      );
    };
    

    Children(子组件)


    我们在本周早些时候谈到了建立父子关系的事情, 但是让我们更详细地介绍一下如何访问父组件中的子组件, 以及如何呈现它们。

    在第11天, 我们构建了一个 组件来处理时钟组件中的日期格式, 以使用户能够灵活地使用自己的自定义时钟渲染。回想一下, 我们所创建的实现实际上是相当丑陋和相对复杂的。

    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 = props => {
      let children = props.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, props))}
        </span>
      );
    };
    
    React.cloneElement

    我们还没有谈论React.cloneElement() 函数, 所以让我们简单地看看它。 记得 WWWWWAAAAAYYYYY(way) 回到第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()为我们处理这个。有时我们会想复制它或添加自定义props/children的组件,而不是创建一个新的组件实例 (如果我们已经有一个)。所以我们可以保留它创建的相同的属性。我们可以用React.cloneElement() 来为我们处理这一切。

    React.cloneElement()React.createElement() 函数有相同的API,参数所在的位置:

    1. The ReactElement we want to clone(我们要克隆的 ReactElement)
    2. Any props we want to add to the instance(我们要添加到实例中的任何 props)
    3. Any children we want it to have.(我们希望它有任何children)

    在我们的 Formatter 示例中, 我们正在创建列表中所有子级 (, 等组件) 并将state 对象作为其属性。

    React.Children 的对象提供了一些很好的实用工具来处理children的函数。上面的 Formatter 示例使用 map 函数循环访问子级, 并在列表中克隆每一个。它为每一个创建一个key (如果需要), 使我们不必自己管理唯一性。

    让我们使用React.Children.map() 函数更新我们的应用组件:

    const App = props => {
      return (
        <ul>
          {React.Children.map(a, i => (
            <li>{i}</li>
          ))}
        </ul>
      );
    };
    

    在浏览器中, 一切仍然正常。
    React教程: 第13天 重复元素_第3张图片
    React.Children 中还有其他一些非常有用的方法,我们将主要使用React.Children.map() 函数,但了解其他可用的 对我们来说也是很好的。 点击文档 查看更多列表。

    通过这一点, 我们只处理了本地数据, 而不是真正关注远程数据 (尽管我们在构建活动提要组件时已经简要地提到了它)。明天, 我们将进入与服务器的互动, 所以我们可以使用它在我们的React应用。

    今天的工作很棒!


    上一章:create-react-app
    下一章:获取远程数据


    本教程系列的完整源代码可以在 GitHub repo, 上找到,其中包含所有样式和代码示例。
    如果在任何时候你感到困扰,有进一步的问题,请随时通过以下方式与我们联系:
    在原文文章末尾评论这篇文章
    发送电子邮件至 [email protected]
    加入我们的 gitter room
    发推文给我们 @fullstackreact
    REACT.JS DOM 应用 移动 JAVASCRIPT
    版权声明 本译文仅用于学习、研究和交流目的,欢迎非商业转载。转载请注明出处、译者和众成翻译的完整链接。
    原文链接:全栈React: React 30天


    如果有疑问可以直接留言评论,如果觉得对你有帮助,可以小小的赞赏一杯奶茶钱,谢谢!!

    在这里插入图片描述

  • 你可能感兴趣的:(前端,#,全栈React)