- 原文地址:The constructor is dead, long live the constructor!
- 原文做者:Donavon West
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:unicar
- 校对者:FateZeros, pot-code
Photo by Samuel Zeller on Unsplash前端
尽管无状态函数组件(SFCs)是一件趁手的神兵利器,但 ES6 类组件仍旧是建立 React 组件及其状态和生命周期钩子函数的默认方式。react
假设一个 ES6 类组件以下例所示(只展现简化过的部分代码)。android
class Foo extends Component {
constructor(props) {
super(props);
this.state = { loading: true };
}
复制代码
async componentDidMount() {
const data = await loadStuff();
this.setState({ loading: false, data });
}
复制代码
render() {
const { loading, data } = this.state;
return (
{loading ? <Loading /> : <View {...data} />}
);
}
}
复制代码
在 constructor
中初始化 state
,并于 componentDidMount
中异步加载数据,而后根据 loading
的状态来渲染 View
这个组件。对我而言这是至关标准的模式,若是你熟悉我以前的代码风格的话。ios
咱们都知道 constructor
正是咱们初始化实例属性的地方,就像本例中这个 state
同样。若是你正成竹在胸地对本身说,『正是如此!』,那么你可说对了……但对于即将问世的 ES.next 类属性提案class properties proposal 而言却并不是如此,目前这份提案正处于第三阶段。git
按照新的提案来讲,咱们能够用以下方式直接定义类属性。es6
class Foo extends Component {
state = { loading: true };
...
}
复制代码
Babel 将会在后台转译你的代码并添加上一个 constructor
。下图是 Babel 将你的代码片断转译过来的结果。github
请注意这里 Babel 其实是传递了全部参数到 super
- 不只仅是 props
。它也会将 super
的返回值传递回调用者。二者虽然感受有些小题大作,但确实须要这样。express
此处仍存在构造函数,你只是看不见而已。后端
使用 constructor
的另外一重缘由是将函数绑定到 this
,以下所示。数组
class Foo extends Component {
constructor(props) {
super(props);
this.myHandler = this.myHandler.bind(this);
}
复制代码
myHandler() {
// some code here that references this
}
...
}
复制代码
但有些人用直接将函数表达式指定给一个类属性的方法彻底避免了这个问题,不过这又是另外一码事了。想了解更多能够参考我写的其余基于 ES6 类的 React 文章。 Demystifying Memory Usage using ES6 React Classes.
Demystifying Memory Usage using ES6 React Classes
那让咱们假设一下你隶属 bind
阵营(即使不是也烦请耐心看完)。咱们仍是得须要在 constructor
进行绑定对吧?那倒不必定了。咱们能够在这里使用和上述处理类属性同样的方法。
class Foo extends Component {
myHandler = this.myHandler.bind(this);
myHandler() {
// some code here that references this
}
...
}
复制代码
那若是你须要从 props
中派生出初始 state
,比方说初始化一个默认值?那这样总该须要使用到 constructor
了吧?
class Foo extends Component {
constructor(props) {
super(props);
this.state = {
color: this.props.initialColor
};
}
render() {
const { color } = this.state;
return (
<div>
{color}
</div>
);
}
}
复制代码
并非哦!类属性再次救人于水火!咱们能够同时取到 this
和 props
。
class Foo extends Component {
state = {
color: this.props.initialColor
};
...
}
复制代码
那也许咱们须要 constructor
获取数据?基本上不须要。就像咱们在第一个代码示例看到的那样,任何数据的加载都应在 componentDidMount
里完成。但为什么独独在 componentDidMount
呢?由于这样能够确保在服务器端运行组件时不会执行获取数据 - 服务器端渲染(SSR)同理 — 由于 componentDidMount
不会在服务器端执行。
综上能够看出,咱们再也不须要一个 constructor
(或者其余任何实例属性)来设置初始 state
。咱们也不须要构造函数来把函数绑定到 this
,以及从 props
设置初始的 state
。同时咱们也彻底不须要在 constructor
里面获取数据。
那为何咱们还须要在 React 组件中使用构造函数呢?
怎么说呢……你还真的不须要
不过,要是你在某些模棱两可的使用实例里,遇到须要同时从客户端和服务器端在一个组件里初始化什么东西的状况,构造函数仍然是个好的出路。你还有 componentWillMount
这个钩子函数能够用。 从内部机制来看,React 在客户端和服务器端都新建好了这个类(即调用构造函数)之后,就会当即调用这个钩子函数。
因此对 React 组件来讲,我坚信这一点:构造函数已死,构造函数万岁!
I also write for the American Express Engineering Blog. Check out my other works and the works of my talented co-workers at AmericanExpress.io. You can also follow me on Twitter.
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。