夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心概念

    • JSX简介
    • 元素渲染
    • 组件&Props
      • 函数组件与 class 组件
        • 1.函数组件
        • 2.class组件
        • 函数组件与Class组件在事件处理上的一些区别
      • 属性展开运算符
      • 渲染组件(父子组件传值)
      • 组合组件(复用组件)
      • 提取组件(拆分组件)
        • props命名原则
        • 提取原则
      • Props 的只读性(不能修改Props)
    • State&生命周期
    • 事件处理
    • 条件渲染
    • 列表&Key
    • 表单
    • 状态提升 (共享状态)
    • 组合vs继承
    • React哲学
  • 高级指引

  • Hook

  • 案例演示

  • Router

  • Redux

  • Jotai

  • Mobx

  • 其他

  • 《React》笔记
  • 核心概念
夜猫子
2021-03-24
目录

组件&Props

# 03. 组件 & Props

# 函数组件与 class 组件

# 1.函数组件

function Welcome(props){
  return <h1>Hello, {props.name}</h1>
}
1
2
3

该函数是一个有效的React组件。接收唯一带有数据的props参数,并返回一个React元素。

# 2.class组件

使用ES6的class来定义:

class Welcome extends React.Component{
  // render 方法描述你想在屏幕看到的内容
  render() {
    return <h1>Hello, {this.props.name}</h1>
  }
}
1
2
3
4
5
6

以上两个组件是等效的。

# 函数组件与Class组件在事件处理上的一些区别

  • 使用class组件时的事件处理: onClick={() => this.props.onClick()}

  • 使用函数组件时的事件处理: onClick={props.onClick}(注意两侧都没有括号)。

class组件特点:

  • 有组件实例
  • 有生命周期
  • 有 state 和 setState

函数组件特点:

  • 没有组件实例
  • 没有生命周期
  • 没有 state 和 setState,只能接收 props
  • 函数组件是一个纯函数,执行完即销毁,无法存储 state

class 组件存在的问题:

  • 大型组件很难拆分和重构,变得难以测试
  • 相同业务逻辑分散到各个方法中,可能会变得混乱
  • 复用逻辑可能变得复杂,如 HOC 、Render Props

所以 react 中更提倡函数式编程,因为函数更灵活,更易拆分,但函数组件太简单,所以出现了hook,hook就是用来增强函数组件功能的。

类组件功能最为完备和强大,某些特殊用途(如错误边界)组件只能写成类式组件。函数组件没有this困扰且代码简洁,大部分的普通组件都可以写成函数组件。

# 属性展开运算符

如果你已经有了一个 props 对象,你可以使用**展开运算符 ...**来在 JSX 中传递整个 props 对象。以下两个组件是等价的:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}
1
2
3
4
5
6
7
8

还可以选择只保留当前组件需要接收的 props,并使用展开运算符将其他 props 传递下去。

const Button = props => {
  const { kind, ...other } = props;
  const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
  return <button className={className} {...other} />;
};
1
2
3
4
5

# 渲染组件(父子组件传值)

React 元素也可以是用户自定义的组件:

const element = <Welcome name="Sara" />;
1

通过属性(attributes)来传递值给子组件:

function Welcome(props) { // 通过props接收传入值
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />; // 通过attributes传入值
ReactDOM.render(
  element,
  document.getElementById('root')
);
1
2
3
4
5
6
7
8
9

注意: 组件名称必须以大写字母开头。

React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome。

# 组合组件(复用组件)

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      // 复用Welcome组件
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

通常来说,每个新的 React 应用程序的顶层组件都是 App 组件

# 提取组件(拆分组件)

参考如下 Comment 组件:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。

首先,提取 Avatar 组件:

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}
1
2
3
4
5
6
7
8

# props命名原则

Avatar 不需知道它在 Comment 组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user,而不是 author。

我们建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。

接下来,我们将提取 UserInfo 组件,该组件在用户名旁渲染 Avatar 组件:

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10

最终的 Comment 组件:

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13

最初看上去,提取组件可能是一件繁重的工作,但是,在大型应用中,构建可复用组件库是完全值得的。

# 提取原则

  • UI中多次被使用的部分
  • 一个足够复杂的组件(页面)

# Props 的只读性(不能修改Props)

组件无论是使用函数声明还是通过 class 声明 (opens new window),都决不能修改自身的 props。

当然,应用程序的 UI 是动态的,并会伴随着时间的推移而变化。在下一章节 (opens new window)中,我们将介绍一种新的概念,称之为 “state”。在不违反上述规则的情况下,state 允许 React 组件随用户操作、网络响应或者其他变化而动态更改输出内容

编辑 (opens new window)
#React
上次更新: 2024/12/19 17:25:54
元素渲染
State&生命周期

← 元素渲染 State&生命周期→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式