发布于 2026-01-06 1 阅读
0

通过重构 React 组件来学习公共类字段语法

通过重构 React 组件来学习公共类字段语法

阅读 React 代码时,你会遇到许多实现相同功能的不同方法。对于初学者来说,这很容易让人感到困惑。你可能会看到的一个区别是 React 类组件使用公共类字段语法。

这种语法并非 React 特有,而是可以用于编写任何 JavaScript 类。在深入探讨之前,需要注意的是,公共和私有类字段声明目前仍处于 TC39 流程的第三阶段。不过,可以通过 Babel 等构建系统来实现此功能(如果您正在编写 React 代码,则很可能已经在使用 Babel 了)。

我个人觉得,如果能看到代码经过多个步骤的重构过程,而不是仅仅看到初始版本和最终版本,就能更好地理解。我们有一个筹款组件,它包含一些状态并渲染两个组件。一个是表单,包含两个输入框,分别用于输入当前金额和目标金额;另一个用于显示这些数据。我们将重构这个组件,使其使用公共类字段语法。

以下是原始组件和最终组件,供您参考。

原装部件

import React from 'react';
import ProgressForm from './ProgressForm.js';
import ProgressBar from './ProgressBar.js';

class Fundraiser extends React.Component {
  constructor(props) {
    super(props);
    this.handleAmountChange = this.handleAmountChange.bind(this);
    this.handleGoalChange= this.handleGoalChange.bind(this);
    this.state = { amount: '',
                   goal: ''
                  };
  }

  handleAmountChange(amount) {
    this.setState({ amount });
  }

  handleGoalChange(goal) {
    this.setState({ goal })
  }

  render() {
    const { goal, amount } = this.state
    return (
      <>
        <ProgressBar amount={amount} goal={goal} />
        <ProgressForm
          onAmountChange={this.handleAmountChange} amount={amount}
          onGoalChange={this.handleGoalChange} goal={goal}
        />
      </>
    );
  }
}

export default Fundraiser;

使用公共类字段语法重构

import React from 'react';
import ProgressForm from './ProgressForm.js';
import ProgressBar from './ProgressBar.js';

class Fundraiser extends React.Component {
  state = { amount: '',
            goal: ''
          };

  handleAmountChange = (amount) => {
    this.setState({ amount });
  }

  handleGoalChange = (goal) => {
    this.setState({ goal })
  }

  render() {
    const { goal, amount } = this.state
    return (
      <>
        <ProgressBar amount={amount} goal={goal} />
        <ProgressForm
          onAmountChange={this.handleAmountChange} amount={amount}
          onGoalChange={this.handleGoalChange} goal={goal}
        />
      </>
    );
  }
}

export default Fundraiser;

让我们看看发生了什么变化!

在我们的初始组件中,我们有一个类,其中包含一些事件处理程序的方法,handleAmountChange以及一个handleGoalChange方法renderconstructor我们在其中设置一些状态,并处理正确的 this 绑定,以确保我们的方法能够按照预期的方式在正确的 this 上下文中工作。

我们首先可以轻松重构的地方是将状态变量从构造函数中移出。使用公共类字段语法,我们可以直接将其定义为类的属性或“字段”。

...
class Fundraiser extends React.Component {
  constructor(props) {
    super(props);
    this.handleAmountChange = this.handleAmountChange.bind(this);
    this.handleGoalChange= this.handleGoalChange.bind(this);
  }
  state = { amount: '',
            goal: ''
          };
...

现在构造函数中只剩下方法的 `this` 绑定了。我们可以通过将方法重构为箭头函数,将这些方法也从构造函数中移出来,这意味着我们可以完全移除构造函数!之所以能做到这一点,是因为箭头函数没有自己的this关键字,所以this关键字是按词法绑定的。

...
class Fundraiser extends React.Component {
  state = { amount: '',
            goal: ''
          };

  handleAmountChange = (amount) => {
    this.setState({ amount });
  }

  handleGoalChange = (goal) => {
    this.setState({ goal })
  }
...

我们的代码现在看起来更易读,而且样板代码也更少了!

但是,我们可能并非总是想使用公共类字段语法……

编写代码时,我们总会面临各种权衡取舍。当向类中添加方法时,其底层原理与将该方法添加到函数原型中相同。当方法位于原型中时,无论创建多少个类实例,它都只会被定义一次。如果我们像上面那样使用类字段来添加方法,代码可能看起来更易读,但类字段会被添加到实例本身,而不是原型中。如果我们创建 100 个实例,就会创建 100 个方法副本!

如果您有任何问题、意见或反馈,请告诉我。关注我,每周都会发布关于 JavaScript、React、Python 和 Django 的最新文章!

文章来源:https://dev.to/guin/learn-public-class-field-syntax-by-refactoring-a-react-component-njh