博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【译】为什么要写super(props)
阅读量:4639 次
发布时间:2019-06-09

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

译注:

原文地址

正文

我听说是新的热点。好笑的是,我想通过描述一些关于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 };  // ...}

之前计划的一种支持plain class的(注:即类变量),已经在2015年,React0.13版中加入。在class fields完整确定之前,定义 constructor 和调用 super(props) 被当做一种临时方案。

但是,让我们回到只使用ES2015的例子里:

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

为什么要调用 super? 能不能不用它?如果不得不用它,在调用它时,发生了什么?还有其他的参数吗?


在JavaScript里,super指向父类构造器。(在我们的例子里, 他指向React.Component实现类)。

重点在于,如果调用了父类构造器,在调用super之前,无法使用this关键字。JavaScript不允许这么干。

class Checkbox extends React.Component {  constructor(props) {    // ? Can’t use `this` yet    super(props);    // ✅ Now it’s okay though    this.state = { isOn: true };  }  // ...}

为什么JavaScript强制在调用this之前执行父类构造器?这里有一个好的解释。考虑一个类的层级结构:

class Person {  constructor(name) {    this.name = name;  }}class PolitePerson extends Person {  constructor(name) {    this.greetColleagues(); // ? This is disallowed, read below why    super(name);  }  greetColleagues() {    alert('Good morning folks!');  }}

想象一下如果在super之前使用this是允许的。一个月之后,我们可能修改greetColleagues来动态加载信息中的姓名。

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

但是我们忘记了this.greetColleagues()是在super()之前调用,它已经和this.name建立了联系。而this.name甚至还没有定义。你能发现,像这样的代码,真的很难理解。

为了避免这样的陷阱, 如果在构造器中调用this,JavaScript强制要求super要在this之前书写,让父类做它们应该做的事。这条限制也被应用到了React组件类定义中:

constructor(props) {    super(props);    // ✅ Okay to use `this` now    this.state = { isOn: true };}

这样就留给我们另一个问题: 为什么要传递props


你也许觉得对于React.Component构造器初始化this.props而言,通过super传递props非常重要。

// Inside Reactclass Component {  constructor(props) {    this.props = props;    // ...  }}

这和真相相去甚远。事实上,这才是。

但不知道为啥,即使你不传入props,直接调用super(),还是可以在render和其他方法里访问到this.props(如果你不相信我,自己试一下)。
这是怎么个情况?它实际上证实了React也会在调用constructor之后,立刻合并props

// Inside Reactconst instance = new YourComponent(props);instance.props = props;

所以即使你忘记把props传递给super(),React也会及时设置上去的。下面是原因之一:

当React支持类方法声明组件时,并不是单单支持了ES6类语法。它的目标是支持所有抽象类范围内的声明方法。JavaScript有很多变种,如ClojureScript, CoffeeScript, ES6, Fable, Scala.js, TypeScript,或者是其他方式,并不是很好比较到底哪种方式去定义一个组件更合适。所以React故意固执得要求super(),虽然ES6 class是这样。

这下明白为什么能只写super()而不用写super(props)了吗?
也许还不明白,没关系,这个东西太令人困惑了。当然,React将会在构造器执行完毕后去合并this.props。但是在super和构造器结尾之间,this.props仍是undefined。

// Inside Reactclass Component {  constructor(props) {    this.props = props;    // ...  }}// Inside your codeclass Button extends React.Component {  constructor(props) {    super(); // ? We forgot to pass props    console.log(props);      // ✅ {}    console.log(this.props); // ? undefined   }  // ...}

如果一些方法在构造器中调用,这样会给debug造成很大的挑战。这也是为什么我推荐传递super(props),虽然它不是必须的。

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

这样确保了this.props在构造器存在前就已经被设置。


还有一点,React长期使用者可能会好奇。

你也许注意到了Context API传递了第二个参数给构造器。(不论是古老的contextTypes还是现在16.6新加的ContextAPI)。
为什么要写super(props, context)来代替super(props)?当然也行,但是context很少使用,所以这个陷阱不常出现。
在class fields提案通过之后,这些陷阱都没得差不多了。没有一个明确的constructor,所有的参数都会自动传递。这也是为什么一个表达式类似state={}可以包含this.propsthis.context引用。
通过使用Hooks,就不需要superthis了。但那是另一个主题了。

转载于:https://www.cnblogs.com/liuyongjia/p/10140071.html

你可能感兴趣的文章
创建、删除表
查看>>
CI接收post与get传输数据
查看>>
禁用缓存
查看>>
显示和编辑注解
查看>>
ArcGIS AddIN之工具不可用
查看>>
配置错误,无法识别的配置节 system.serviceModel 解决方案
查看>>
oc学习
查看>>
Java生鲜电商平台-Linux服务器常用升级的基础包
查看>>
聊天室(C++客户端+Pyhton服务器)2.基本功能添加
查看>>
swift中try
查看>>
缓存框架Ehcache相关
查看>>
用Instant client批量安装Oracle客户端-安装配置
查看>>
Fireworks为枝繁叶茂的树木图片抠底
查看>>
iphone 开发学习整理
查看>>
自我介绍
查看>>
Prof. Dr. Ligang Liu (刘利刚) 中国科技大学
查看>>
centos 升级openssl
查看>>
Ubuntu下安装 Mono(整理)
查看>>
Python Tkinter 学习成果:点歌软件music
查看>>
虚方法(virtual)和抽象方法(abstract)的区别
查看>>