在构造函数中定义状态还是使用属性初始化器更好?

Posted

技术标签:

【中文标题】在构造函数中定义状态还是使用属性初始化器更好?【英文标题】:Is it better to define state in constructor or using property initializers? 【发布时间】:2016-10-13 18:55:52 【问题描述】:

根据this babel 文档,使用 ES6+ 和 React 的正确方法是像这样初始化组件:

class Video extends React.Component 
  static defaultProps = 
    autoPlay: false,
    maxLoops: 10,
  
  static propTypes = 
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
  
  state = 
    loopsRemaining: this.props.maxLoops,
  

但是一些官方的例子,比如 Dan Abramov 自己的 React DnD 模块,使用 ES6+ 但仍然在构造函数中定义状态:

constructor(props) 
    super(props);
    this.moveCard = this.moveCard.bind(this);
    this.state = 
       // state stuff
    

现在 Dan Abramov,作为 React 的重要贡献者,可能知道他可以在构造函数之外定义状态,但仍然选择在构造函数中进行。

所以我只是想知道哪种方式更好,为什么?

【问题讨论】:

没有好坏之分,都是等价的,看个人喜好 类属性是一个提案。它们不是 ES7 的一部分。请至少阅读标签说明:ecmascript-7. 不再需要构造函数***.com/a/63109619/2761641 【参考方案1】:

我相信这是个人喜好问题。转译后的输出在语义上是相同的。

Class Property Constructor

【讨论】:

如果类extends React.Component,它们不会转译为相同的东西 是的,很公平,但是this.state 的语义没有改变。【参考方案2】:

它们是等价的,因为class field proposal 是构造函数主体代码的语法糖。

如果不需要显式构造函数(创建临时局部变量等),可以省略 constructor 以支持类字段。

显式构造函数的问题是super参数(props)经常被错误地省略,这可能会导致问题:

constructor() 
    super();
    this.state =  foo: this.props.foo  // this.props is undefined

显式构造函数可能有利于可读性。方法常规放在constructor下面,甚至是箭头属性。这不会按预期工作,因为类字段是按照它们列出的顺序分配的:

state =  foo:  method: this.someMethod   // this.someMethod is undefined

someMethod = () => ...;

在这种情况下,显式构造函数可能会产生更易读的代码:

constructor(props) 
    super(props);

    // <-- this is the place where this.someMethod is really assigned

    this.state =  foo:  method: this.someMethod  


someMethod = () => ...;

【讨论】:

【参考方案3】:

Dan 的代码实际上有一个微妙的错误,这就是为什么我建议尽可能使用初始化程序。 React 组件构造函数有两个参数 - props 和 上下文。他没有将它传递给父构造函数,其他需要它的开发人员很容易错过它。

有时你别无选择,比如初始化器依赖于构造函数参数时,所以记得将所有参数传递给父级。

在尝试了一些事情之后,看起来 React 没有我想的问题。你可以将任何你想要的东西传递给父构造函数,它会很好。例如:

class MyComponent extends React.Component 
  constructor(props) 
    super()
  

  render() 
    // this.props will still be set correctly here
  

我仍然建议使用初始化程序,因为不必调用父构造函数是一件需要考虑的事情。

【讨论】:

我不知道 React 构造函数有两个参数。上下文是什么? 这是一种将数据传递给层次结构更深层次的组件的方法,而无需在所有中介上设置 props。我尝试了一些测试,看起来 React 没有我提到的问题。不过,点仍然有效。 “你可以将任何你想要的东西传递给父构造函数,它会很好” - 不。 facebook.github.io/react/docs/react-component.html#constructor 还有:facebook.github.io/react/docs/state-and-lifecycle.html 文档并不总是与现实相符。并不是说人们应该忽略文档,只是指出 React 实际上的行为不同。 github.com/facebook/react/blob/…

以上是关于在构造函数中定义状态还是使用属性初始化器更好?的主要内容,如果未能解决你的问题,请参考以下文章

Vue Prop 没有初始化器,也没有在构造函数中明确赋值

Kotlin类的初始化 ② ( 主构造函数 | 主构造函数定义临时变量 | 主构造函数中定义成员属性 | 次构造函数 | 构造函数默认参数 )

属性 '...' 没有初始化器,也没有在构造函数中明确分配

反应:在构造函数上绑定方法时,在 setState 内实现计时器,状态属性未定义

swift学习笔记构造过程

React 中是不是仍需要带有自动绑定和属性初始值设定项的构造函数