如何编写你的第一个 React.js 组件

2025-06-07

如何编写你的第一个 React.js 组件

本文是我在 Pluralsight 课程React.js:入门的部分内容 。我在那里以视频形式介绍了类似的内容。

在 React.js 中,最需要理解的概念是组件。React 组件可以分为两种类型:函数组件组件。有时你会听到不同的术语来描述这两种类型,例如无状态组件和有状态组件。函数组件也经常与表示概念相关联。在本文中,我将它们分别称为函数组件和类组件。

函数组件是 React 组件最简单的形式。它是一个具有简单契约的简单函数:


截图来自我的 Pluralsight 课程 —  React.js:入门

函数组件接收一个属性对象,该对象通常名为props。它返回的内容看起来像 HTML,但实际上是一种称为JSX 的特殊 JavaScript 语法。

类组件定义 React 组件的一种更具特色的方式。它的作用类似于接收 props 的函数,但该函数还将私有的内部状态视为控制返回 JSX 的附加输入。


截图来自我的 Pluralsight 课程 —  React.js:入门

这种私有的内部状态赋予了 React响应式的特性。当类组件的状态发生变化时,React 会在浏览器中重新渲染该组件。

State 对象和 Props 对象有一个重要的区别。在类组件内部,State 对象可以更改,而 Props 对象表示固定值。类组件只能更改其内部状态,而不能更改其属性。这是理解 React 的核心思想,本文将通过一个示例来说明。

我们来看一个组件的实际示例。一个非常简单的组件,没有任何输入,只有一个简单的h1输出div


截图来自我的 Pluralsight 课程 —  React.js:入门

左侧,组件是用特殊的 JSX 语法编写的。

JSX 允许我们使用非常接近 HTML 的语法来描述用户界面 (UI)。然而,它是可选的。React 可以在没有 JSX 的情况下使用,如您在右侧所见。实际上,React 只是将您在左侧看到的 JSX 编译为您在右侧看到的纯 JavaScript。然后,它就可以在浏览器中使用编译后的 JavaScript 了。

React.createElement右侧的调用是文档对象模型(DOM)的 JavaScript 表示。React高效地将其转换为在浏览器中执行的 DOM 操作。

让我们编写一个 React 组件。

我将使用 jsComplete 的React Playground作为本文的示例。它是一个可以直接在浏览器中测试 JavaScript 和 React 代码的工具。无需安装或配置任何东西。

该工具拥有简洁的双面板界面。左侧面板是编辑器,您可以在其中编写 JavaScript 和 React 代码。React 和 ReactDOM 的最新版本都已预装在编辑器中。编辑器还能识别 JSX 扩展和 JavaScript 中的所有现代特性。这使得我们可以专注于 React API 本身,而不是配置和编译 React 应用程序。

右侧面板是预览面板。编辑器中有一个预定义mountNode元素。执行 JavaScript 代码时,您在mountNode元素中输入的任何内容都会显示在预览面板中。预览面板还会显示您在执行代码时遇到的任何错误。这个 Playground 也是一个简单的 JavaScript REPL(运行、求值、打印、循环),您可以在其中测试快速的 JavaScript 函数和表达式。要随时执行代码,请按CTRL+Enter

例如,尝试以下操作:

mountNode.innerHTML = 'Hello!!';
Enter fullscreen mode Exit fullscreen mode

或者简单的 REPL 模式

3 == '3'
Enter fullscreen mode Exit fullscreen mode

要创建 React 组件,请定义一个新函数。让我们让该函数返回一个 HTML 按钮元素:

function Button() { 
  return ( 
    <button>Go</button> 
  );
}
Enter fullscreen mode Exit fullscreen mode

我们在这里返回的内容看起来像 HTML,但请记住它不是。它将被编译成 JavaScript。当我们在 JSX 中使用此按钮元素时,浏览器实际看到的 JavaScript 是对以下React.createElement函数的调用:

function Button() { 
  return ( 
    React.createElement("button", null, "Go") 
  );
}
Enter fullscreen mode Exit fullscreen mode

虽然你也可以不使用 JSX 来以这种方式使用 React,但编码和维护起来会困难得多。所以,我们还是坚持使用 JSX 吧。

上面的函数是一个完整且非常简单的 React 组件。让我们使用它吧!

我们通过将组件挂载到浏览器中来使用它。为此设计的函数是ReactDOM.render,它接受两个参数:

  • 第一个是要渲染的组件,在我们的例子中是Button
  • 第二个参数是该组件应该渲染到哪个元素中。在 REPL 的环境中,我们可以使用特殊mountNode变量。
ReactDOM.render(<Button />, mountNode);
Enter fullscreen mode Exit fullscreen mode

本文中的所有代码示例在屏幕截图标题中都有一个链接,您可以在 jsComplete REPL 上编辑示例。

React 函数组件的第一个参数是该props对象。这个参数允许我们让组件可复用。例如,我们不需要对上面按钮的“Go”标签进行硬编码,而是可以像处理普通 HTML 元素一样,给Button组件传递一个label属性:

ReactDOM.render(<Button label="Save" />, mountNode);
Enter fullscreen mode Exit fullscreen mode

然后我们可以使用花括号在组件内部访问此属性props.label

function Button(props) { 
  return ( 
    <button>{props.label}</button> 
  );
}
Enter fullscreen mode Exit fullscreen mode

参数props是一个对象,它保存了渲染组件时传递给组件的所有值。

使组件具有交互性

我们有一个按钮元素,它是通过 React 组件呈现的。

现在让我们为这个目前为止比较枯燥的示例添加一些交互功能。让我们让按钮元素在每次点击时增加一个计数器值,并将该值显示为按钮本身的标签。因此,这个按钮的标签将从数字 1 开始,当用户点击按钮时,它的标签将变为 2、3、4,依此类推。

由于这需要在组件渲染输出中体现,因此它属于组件的状态。我们需要组件在每次计数器更改时重新渲染自身。我们不能在这里使用属性,因为组件的 props 无法更改。通过使用特殊的 React 状态对象,我们将利用 React 的响应式特性,无需担心如何将更改传递到浏览器。React 会为我们完成这项工作。

但是,我们的 Button 组件目前是一个函数组件。函数组件无法拥有状态,所以我们需要先将其升级为类组件。

这很简单。我们首先定义一个扩展类React.Component

class Button extends React.Component { }
Enter fullscreen mode Exit fullscreen mode

在该类中,我们定义了一个render函数,它返回组件的 JSX;在我们的例子中是 HTML 按钮。

render() { 
  return ( 
    <button>1</button> 
  );
}
Enter fullscreen mode Exit fullscreen mode

这是更多的代码,但是我们现在可以在 Button 组件上使用私有状态!

要使用状态对象,首先需要初始化它。状态对象是一个简单的实例属性,因此我们可以在Button类的构造函数中初始化它。我们只需定义一个普通的构造函数(在 React 中接收一个props对象)并调用该super方法即可,以遵循组件的继承关系。

constructor(props) { 
  super(props); 
  this.state = { counter: 1 };
 }
Enter fullscreen mode Exit fullscreen mode

之后,我们将其初始化this.state为所需的值。此状态对象的键是状态的各个元素。对于我们的情况,我们需要一个counter从 1 开始的状态。

counter在渲染函数内部,由于我们可以在花括号内编写任何 JavaScript 表达式,因此我们可以读取使用在状态上初始化的新状态元素的值this.state.counter

render() { 
  return ( 
    <button>{this.state.counter}</button>
  );
}
Enter fullscreen mode Exit fullscreen mode

this”关键字指的是我们要传递的组件实例ReactDOM

您可以尝试更改该计数器状态,以查看按钮如何呈现您在该状态上输入的值。

还有另一种更短的语法来定义初始状态,即简单地使用类属性而不调用构造函数:

class Button extends React.Component { 
  state = { counter: 1 }; 
  render() { 
    return ( 
      <button>{this.state.counter}</button> 
    ); 
  }
}
Enter fullscreen mode Exit fullscreen mode

这还不是官方 JavaScript 语言的一部分,但很快就会成为官方 JavaScript 语言。该语法在 jsComplele REPL 环境中有效,因为该工具使用 Babel 将其转换为浏览器可以理解的 JavaScript。

当你配置自己的 React 应用程序时,无论如何都必须使用类似 Babel 的工具将 JSX 编译成 JavaScript。同时,包含并使用即将成为该语言正式组成部分的 JavaScript 特性也是一件轻而易举的事。

在目前的示例中Button,我们有一个状态对象和一个 HTML 按钮元素,该按钮元素显示我们在状态上初始化的计数器值。现在我们需要在点击按钮时更改该值。我们需要在该按钮上定义一个点击处理程序。

React 自带了易于使用的规范化事件。在本例中,我们需要onClick在 HTML 按钮元素上定义事件:

function F() {}

<button onClick={F} />
Enter fullscreen mode Exit fullscreen mode

与使用字符串的 DOM 事件处理程序不同,React 事件处理程序使用实际的 JavaScript 函数。此函数可以是全局函数(F如上所示),也可以是内联函数:

<button onClick={() => {}} />
Enter fullscreen mode Exit fullscreen mode

但是,标准做法是在类组件本身上定义一个函数。handleClick我们可以在组件上将其定义为实例属性来调用它:

class Button extends React.Component { 
  state = { counter: 1 }; 

  handleClick = () => { 
    console.log('Button is clicked!!'); 
  }; 

  render() { 
    return ( 
      <button onClick={this.handleClick}> {this.state.counter} </button> 
    ); 
  }
}
Enter fullscreen mode Exit fullscreen mode

我们使用的是现代的类字段语法,它允许我们使用绑定到组件实例的箭头函数。handleClick现在将充当此类的原型函数。handleClick关键字“ this”指的是我们正在 DOM 中挂载的组件实例。

handleClick的工作很简单:使用 从状态对象中读取当前计数器值this.state.counter。然后增加此值,并用新的增加值更新组件状态。

我们可以使用 React 的内置setState方法(每个类组件实例上都有)来更新组件状态。

现在,每次点击按钮时,其标签都会增加。

这很简单,但功能强大!我们为该onClick方法定义了一个事件处理程序。每次用户点击按钮时,该handleClick函数都会被执行。该函数读取计数器值的当前状态,将其递增,然后将状态设置为新的递增值。React 会负责这些更改后所需的所有渲染,因此您无需担心。

请注意,我们没有直接更新状态对象。当我们想要更新状态中的任何元素时,必须使用 React 的setState方法。例如,你不能这样做:

// WRONG:
this.state.counter = this.state.counter + 1;
Enter fullscreen mode Exit fullscreen mode

React 的setState方法是异步的,它会安排更新。setState为了提高性能,可能会将多个调用分批处理。由于我们在handleClick函数内部同时读取和写入状态对象,因此可能会遇到竞争条件。一般的经验法则是,每当您需要使用当前状态的值更新状态时,请使用该setState方法的另一个契约。它接收一个函数引用而不是对象作为其第一个参数:

this.setState((prevState) => {});
Enter fullscreen mode Exit fullscreen mode

这个函数接收一个prevState我们可以放心使用的对象,不用担心竞争条件。该函数返回我们希望 React 用来设置状态的对象。我们counter上面的值示例变成了:

this.setState((prevState) => ({
  counter: prevState.counter + 1 
}));
Enter fullscreen mode Exit fullscreen mode

只有当更新依赖于当前状态时,才需要使用第二种语法setState。不过,养成始终使用第二种函数参数语法的习惯可能是一个好主意。

最终代码如下:

class Button extends React.Component {
  state = { counter: 1 };

  handleClick = () => {
    this.setState((prevState) => ({
      counter: prevState.counter + 1 
    }));
  };

  render() {
    return (
      <button onClick={this.handleClick}>
        {thi
        s.state.counter}
      </button>
    );
  }
}

ReactDOM.render(<Button />, mountNode);
Enter fullscreen mode Exit fullscreen mode

测试一下,如果有任何问题请告诉我。


还在学习 React 还是 Node?看看我的书:


本文最初发表于此处

文章来源:https://dev.to/samerbuna/how-to-write-your-first-reactjs-component-191i
PREV
2018 年你应该学习哪些 JavaScript 框架?
NEXT
typia(速度快 20,000 倍的验证器)凭借其编译器技能向 Agentic AI 框架发起挑战