在React组件中,使用构造函数和state = {}声明状态有什么区别?

34

我发现在类组件中声明状态有两种方式,如下所示:

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            name: 'John'
        }
    }

    render() {
        return  <div>{this.state.name}</div>
    }

}

class App extends Component {
    state = {
       name: 'John'
    }

    render() {
        return  <div>{this.state.name}</div>
    }

}

这两者之间有什么区别?

3个回答

23

它们在基本上是等价的。显著的区别是第二个示例中的初始化程序在constructor之前执行。

第二种方法使用了类字段提案。

它还不是ECMAScript标准的一部分,因此您需要正确设置转译器才能使用第二种方法。

更新 查看Babel输出结果以更好地了解公共实例字段的工作原理。


6

当您想将props数据保存到state中时,请使用构造函数

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      name: 'John'
    }
  }
}

否则,您可以直接为硬编码数据设置状态。
class App extends Component {
  state = {
    name: 'John'
  }
}

1
显然这不再是有效的了。我成功地将props的值直接赋给了类中的状态state = { time:this.props.time, }; - Dawid Adach
将prop添加到状态通常被认为是一种反模式:https://reactjs.org/docs/react-component.html#constructor。除非您想显式地派生状态。 - Remi

1
当您向类添加方法时,实际上是将其添加到函数的原型中。如下所示:
class Same{
  thing() {}
}

// Equivalent to:

function Same() {}
Same.prototype.thing = function () {}

"

thing只被定义一次,然后在类的所有实例之间共享。

如果您进行重构以使用以下Class Fields:

"
class Animal {
  thing() {}
  anotherThing = () => {} // Class Field
}

// Equivalent to:

function Animal () {
  this.anotherThing = function () {}
}

Animal.prototype.thing = function () {}

anotherThing在每个新创建的实例上定义,而不是在原型上定义。

开发经验 vs 性能

这是一个你应该考虑的权衡。类字段使你的代码看起来可读性强、干净整洁。然而,类字段在每个实例中都保留了 anotherThing 的副本。

因此,你应该仔细考虑是否要使用它们。


“Class Fields在每个实例中都保存了anotherThing的副本”,这不也是构造函数所做的吗? - vikrant
1
嗨@vikrant!如果我理解正确,你的问题源于OOP继承(例如在Java中)。在Java中,构造函数确实为每个实例创建了anotherThing。在Javascript中,情况“略有”不同。原型链为每个实例保留了对anotherThing的引用,这使它们轻巧且高效。Kyle Simpson的一系列优秀书籍揭示了Javascript基础知识的精髓。我强烈建议您特别阅读本节:https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md - Tomer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接