React的核心概念—组件

文章介绍了React中的核心概念——组件,它是构建用户界面的基础。组件是可复用的UI元素,可以通过组合、排序和嵌套来创建复杂的页面结构。定义组件涉及导出、函数定义以及使用JSX返回HTML标签。文章还讨论了组件的导入与导出,包括默认导出和具名导出,以及如何在不同文件间组织和重用组件。
摘要由CSDN通过智能技术生成

参考文章

组件的定义和使用

组件是 React 的核心概念之一。它们是构建用户界面(UI)的基础。

组件:UI 构成要素

在 Web 当中,HTML 允许使用其内置的标签集(如 <h1><li>)创建丰富的结构化文档:

<article>
  <h1>我的第一个组件</h1>
  <ol>
    <li>组件:UI 构成要素</li>
    <li>定义组件</li>
    <li>使用组件</li>
  </ol>
</article>

<article> 表示这篇文章,<h1> 表示文章的标题,<ol> 以有序列表的形式表示文章的(缩写的)目录。每一个侧边栏、头像、模态框、下拉框的背后都是像这样的(结合了用于样式的 CSS 和用于交互的 JavaScript的)标签——在 Web 上看到的每一个 UI 模块。

React 允许将标签、CSS 和 JavaScript 组合成自定义“组件”,即应用程序中可复用的 UI 元素。 上文中表示目录的代码可以改写成一个能够在每个页面中渲染的 <TableOfContents /> 组件。实际上,使用的依然是 <article><h1> 等相同的 HTML 标签。

就像使用 HTML 标签一样,可以组合、排序和嵌套组件来绘制整个页面。例如,下面的文档页面就是由 React 组件构成的:

<PageLayout>
  <NavigationHeader>
    <SearchBar />
    <Link to="/docs">文档</Link>
  </NavigationHeader>
  <Sidebar />
  <PageContent>
    <TableOfContents />
    <DocumentationText />
  </PageContent>
</PageLayout>

随着项目的发展,会发现很多布局可以通过复用已经完成的组件来实现,从而加快开发进程。上文中提到的目录可以通过 <TableOfContents /> 组件添加到任意的画面中!也可以使用 React 开源社区分享的大量组件(例如 Chakra UIMaterial UI)来快速启动项目。

定义组件

一直以来,创建网页时,Web 开发人员会用标签描述内容,然后通过 JavaScript 来增加交互。这种在 Web 上添加交互的方式能产生出色的效果。现在许多网站和全部应用都需要交互。React 最为重视交互性且使用了相同的处理方式:React 组件是一段可以 使用标签进行扩展 的 JavaScript 函数。如下所示:

export default function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3Am.jpg"
      alt="Katherine Johnson"
    />
  )
}

以下是构建组件的方法:

第一步:导出组件

export default 前缀是一种 JavaScript 标准语法(非 React 的特性)。它允许导出一个文件中的主要函数以便以后可以从其他文件引入它。

第二步:定义函数

使用 function Profile() { } 定义名为 Profile 的 JavaScript 函数。

注意:React 组件是常规的 JavaScript 函数,但组件的名称必须以大写字母开头,否则它们将无法运行!

第三步:添加标签

这个组件返回一个带有 srcalt 属性的 <img /> 标签。<img /> 写得像 HTML,但实际上是 JavaScript!这种语法被称为 JSX,它允许在 JavaScript 中嵌入使用标签。

返回语句可以全写在一行上,如下面组件中所示:

return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />;

但是,如果标签和 return 关键字不在同一行,则必须把它包裹在一对括号中,如下所示:

return (
  <div>
    <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
  </div>
);

注意:没有括号包裹的话,任何在 return 下一行(后面)的代码都 将被忽略

使用组件

现在已经定义了 Profile 组件,可以在其他组件中使用它。例如,可以导出一个内部使用了多个 Profile 组件的 Gallery 组件:

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>了不起的科学家</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

浏览器所看到的

注意下面两者的区别:

  • <section>是小写的,所以 React 知道指的是 HTML 标签。
  • <Profile /> 以大写 P 开头,所以 React 知道想要使用名为 Profile 的组件。

然而 Profile 包含更多的 HTML:<img />。这是浏览器最后所看到的:

<section>
  <h1>了不起的科学家</h1>
  <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
  <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
  <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</section>

嵌套和组织组件

组件是常规的 JavaScript 函数,所以可以将多个组件保存在同一份文件中。当组件相对较小或彼此紧密相关时,这是一种省事的处理方式。如果这个文件变得臃肿,也可以随时将 Profile 移动到单独的文件中。

因为 Profile 组件在 Gallery 组件中渲染,甚至好几次!可以认为 Gallery 是一个 父组件, 将每个 Profile 渲染为一个“孩子”。这是 React 的神奇之处:可以只定义组件一次,然后按需多处和多次使用。

注意:组件可以渲染其他组件,但是 请不要嵌套他们的定义

export default function Gallery() {
  // 永远不要在组件中定义组件
  function Profile() {
    // ...
  }
  // ...
}

上面这段代码 非常慢,并且会导致 bug 产生。 因此,应该在顶层定义每个组件:

export default function Gallery() {
  // ...
}

// 在顶层声明组件
function Profile() {
  // ...
}

当子组件需要使用父组件的数据时,需要 通过 props 的形式进行传递,而不是嵌套定义。

摘要

React关键点:

  • React 允许创建组件,应用程序的可复用 UI 元素。
  • 在 React 应用程序中,每一个 UI 模块都是一个组件。
  • React 是常规的 JavaScript 函数,除了:
    1. 它们的名字总是以大写字母开头。
    2. 它们返回 JSX 标签。

参考文章

组件的导入与导出

组件的神奇之处在于它们的可重用性:可以创建一个由其他组件构成的组件。但当嵌套了越来越多的组件时,则需要将它们拆分成不同的文件。这样可以使得查找文件更加容易,并且能在更多地方复用这些组件。

根组件文件

创建一个 Profile 组件,并且渲染在 Gallery 组件里。

// App.js
function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>了不起的科学家们</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

在此示例中,所有组件目前都定义在根组件 App.js 文件中,在 Create React App 中,应用应在 src/App.js 文件中定义。具体还需根据项目配置决定,有些根组件可能会声明在其他文件中。如果使用的框架基于文件进行路由,如 Next.js,那每个页面的根组件都会不一样。

导出和导入一个组件

如果将来需要在首页添加关于科学书籍的列表,亦或者需要将所有的资料信息移动到其他文件。这时将 Gallery 组件和 Profile 组件移出根组件文件会更加合理。这会使组件更加模块化,并且可在其他文件中复用。可以根据以下三个步骤对组件进行拆分:

  1. 创建 一个新的 JS 文件来存放该组件。
  2. 导出 该文件中的函数组件(可以使用 默认导出具名导出
  3. 在需要使用该组件的文件中 导入(可以根据相应的导出方式使用 默认导入具名导入)。

这里将 Profile 组件和 Gallery 组件,从 App.js 文件中移动到了 Gallery.js 文件中。修改后,即可在 App.js 中导入 Gallery.js 中的 Gallery 组件:

// App.js
import Gallery from './Gallery.js';

export default function App() {
  return (
    <Gallery />
  );
}
// Gallery.js
function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>了不起的科学家们</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

该示例中需要注意的是,如何将组件拆分成两个文件:

  1. Gallery.js:
    • 定义了 Profile 组件,该组件仅在该文件内使用,没有被导出。
    • 使用 默认导出 的方式,将 Gallery 组件导出
  2. App.js:
    • 使用 默认导入 的方式,从 Gallery.js 中导入 Gallery 组件。
    • 使用 默认导出 的方式,将根组件 App 导出。

注意:引入过程中,可能会遇到一些文件并未添加 .js 文件后缀,如下所示:

import Gallery from './Gallery';

无论是 './Gallery.js' 还是 './Gallery',在 React 里都能正常使用,只是前者更符合 原生 ES 模块

从同一文件中导出和导入多个组件

如果只想展示一个 Profile 组件,而不展示整个图集。也可以导出 Profile 组件。但 Gallery.js 中已包含 默认 导出,此时,不能定义 两个 默认导出。但可以将其在新文件中进行默认导出,或者将 Profile 进行 具名 导出。同一文件中,有且仅有一个默认导出,但可以有多个具名导出!

注意:为了减少在默认导出和具名导出之间的混淆,一些团队会选择只使用一种风格(默认或者具名),或者禁止在单个文件内混合使用。这因人而异,选择最适合的即可!

首先,用具名导出的方式,将 Profile 组件从 Gallery.js 导出(不使用 default 关键字):

export function Profile() {
  // ...
}

接着,用具名导入的方式,从 Gallery.js 文件中 导入 Profile 组件(用大括号):

import { Profile } from './Gallery.js';

最后,在 App 组件里 渲染 <Profile />

export default function App() {
  return <Profile />;
}

现在,Gallery.js 包含两个导出:一个是默认导出的 Gallery,另一个是具名导出的 ProfileApp.js 中均导入了这两个组件。尝试将 <Profile /> 改成 <Gallery />,回到示例中:

// App.js
import Gallery from './Gallery.js';
import { Profile } from './Gallery.js';

export default function App() {
  return (
    <Profile />
  );
}
// Gallery.js
export function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>了不起的科学家们</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

示例中混合使用了默认导出和具名导出:

  • Gallery.js
    • 使用 具名导出 的方式,将 Profile 组件导出,并取名为 Profile
    • 使用 默认导出 的方式,将 Gallery 组件导出。
  • App.js
    • 使用 具名导入 的方式,从 Gallery.js 中导入 Profile 组件,并取名为 Profile
    • 使用 默认导入 的方式,从 Gallery.js 中导入 Gallery 组件。
    • 使用 默认导出 的方式,将根组件 App 导出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值