博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
讲道理,React中,我们为什么需要写 super(props)?
阅读量:7113 次
发布时间:2019-06-28

本文共 3357 字,大约阅读时间需要 11 分钟。

这篇文章源自 。

现在的热点是 ,所以 Dan 决定写一篇关于 class 组件的文章 ?。

文章中描述的问题,应该不会影响你写代码;不过如果你想深入研究 React 是怎么工作的,这篇文章可能会对你有帮助。

第一个问题:


我自己都不知道我写了多少遍 super(props)

class Checkbox extends React.Component {  constructor(props) {    super(props);    this.state = { isOn: true };  }  // ...}复制代码

当然, 可以简化代码:

class Checkbox extends React.Component {  state = { isOn: true };  // ...}复制代码

2015 年初的时候,React 0.13 版本就已经支持该语法。在此之前,我们需要不断地写 constructor,然后再调用 super(props)

现在我们先回顾一下之前的写法:

class Checkbox extends React.Component {  constructor(props) {    super(props);    this.state = { isOn: true };  }  // ...}复制代码

我们为什么要调用 super?能不能不调用?如果调用的时候不传入props呢?还可以传入其他参数么?带着这些问题往下看。


在 JavaScript 中,super 引用的是父类构造函数。(在 React 中,引用的自然就是 React.Component

需要注意的是,在调用父类构造函数之前,无法用 this。其实这不是 React 的限制,而是 JavaScript 的限制:

class Checkbox extends React.Component {  constructor(props) {    // ? 还不能用 `this`    super(props);    // ✅ 现在就能用啦    this.state = { isOn: true };  }  // ...}复制代码

JavaScript 对 this 使用的限制,是有原因的。假设有如下的继承:

class Person {  constructor(name) {    this.name = name;  }}class PolitePerson extends Person {  constructor(name) {    this.greetColleagues(); // ? 不能这么干,下面会讲原因    super(name);  }  greetColleagues() {    alert('Good morning folks!');  }}复制代码

如果 JavaScript 允许在调用 super 之前使用 this,一个月之后,我们需要修改 greetColleagues 方法,方法中使用了 name 属性:

greetColleagues() {  alert('Good morning folks!');  alert('My name is ' + this.name + ', nice to meet you!');}复制代码

不过我们可能已经忘了 this.greetColleagues(); 是在调用 super 之前调用的;因此,this.name 还没有赋值。这样的代码,很难定位 bug。

为了避免这样的错误,JavaScript 强制开发者在构造函数中先调用 super,才能使用this这一限制,也被应用到了 React 组件:

constructor(props) {  super(props);  // ✅ 现在可以用 `this` 啦  this.state = { isOn: true };}复制代码

问题又来了:为什么要传入 props 呢?


你可能以为必须给 super 传入 props,否则 React.Component 就没法初始化 this.props

// Inside Reactclass Component {  constructor(props) {    this.props = props;    // ...  }}复制代码

en...离真相不远 —— 事实上,React 也的确。

不过,如果你不小心漏传了 props,直接调用了 super(),你仍然可以在 render 和其他方法中访问 this.props(不信的话可以试试嘛)。

为啥这样也行?因为React 会在构造函数被调用之后,会把 props 赋值给刚刚创建的实例对象:

// Inside Reactconst instance = new YourComponent(props);instance.props = props;复制代码

props 不传也能用,是有原因的。

React 添加对 class 支持的时候,不仅仅要支持 ES6 的 class,还需要考虑其他的 class 实现, CoffeeScript, ES6, Fable, Scala.js, TypeScript 中 class 的使用方式并。所以,即使有了 ES6 class,在调用 super()这个问题上,React 没做太多限制。

但这意味着你在使用 React 时,可以用 super() 代替 super(props) 了么?

别这么干,因为会带来其他问题。 虽然 React 会在构造函数运行之后,为 this.props 赋值,但在 super() 调用之后与构造函数结束之前, this.props 仍然是没法用的。

// Inside Reactclass Component {  constructor(props) {    this.props = props;    // ...  }}// Inside your codeclass Button extends React.Component {  constructor(props) {    super(); // ? 忘了传入 props    console.log(props); // ✅ {}    console.log(this.props); // ? undefined  }  // ...}复制代码

要是构造函数中调用了某个访问 props 的方法,那这个 bug 就更难定位了。因此我强烈建议始终使用super(props),即使这不是必须的:

class Button extends React.Component {  constructor(props) {    super(props); // ✅ We passed props    console.log(props); // ✅ {}    console.log(this.props); // ✅ {}  }  // ...}复制代码

上面的代码确保 this.props 始终是有值的。


还有一个问题可能困扰 React 开发者很久了。你应该已经注意到,当你在 class 中使用 Context API 时(无论是之前的 contextTypes 还是现在的 contextType API),context 都是作为构造函数的第二个参数。

我们为什么不用写 super(props, context)?我们当然可以这么写,不过 context API 用的相对较少,所以引发的 bug 也比较少。

感谢 ,这样的 bug 几近绝迹。只要没有显式声明构造函数,所有参数都会被自动传递。所以,在state = {} 表达式中,你可以访问this.props 以及 this.context

转载于:https://juejin.im/post/5c034e0f6fb9a04a016410c6

你可能感兴趣的文章
vs 2010 sn 序列号
查看>>
js获取下拉框的value值
查看>>
LeetCode OJ:Permutations(排列)
查看>>
云科技时代:阿里云创造者写了《在线》,这是一本怎样的书?
查看>>
PyQt5:常用控件
查看>>
WordPress部署踩坑记
查看>>
sublime-snippets 插件编写
查看>>
代码规范
查看>>
Leetcode | Length of Last Word
查看>>
2017.4.16关于在线图书商城注册界面总结
查看>>
HTML基础
查看>>
MyBatis初探
查看>>
线程和进程的区别
查看>>
[POI2008]Station
查看>>
王昆扬老师发来的材料:关于实数的构造
查看>>
[转] Javascript继承机制的设计思想
查看>>
夜间模式的开启与关闭,父模板的制作
查看>>
ffmpeg为视频添加时间戳 - 手动编译ffmpeg
查看>>
C# ABP 配置连接数据库&创建表
查看>>
1189:Pell数列
查看>>