先来几个术语:
官方 我的说法 对应代码React element React元素 let element=<span>A爆了</span>
Component 组件 class App extends React.Component {}
无 App为父元素,App1为子元素 <App><App1></App1></App>
本文重点:
组件有两个特性
1、传入了一个“props”
2、返回了一个React元素
组件的构造函数
如果需要重新定义constructor,必须super一下,才能激活this,也就是可以用来自React.component方法
组件的props
是可读的,也就是不能在组件中修改prop的属性
JSX中传入对象的props,可以通过{...object}的方式
父子元素之间的通信(初级版本)
父=>子,通过父元素的render既可改变子元素的内容。
子=>夫,通过父元素传入子元素中的props上挂载的方法,让子元素触发父元素中的方法,从而进行通信。
Component上回说到JSX的用法,这回要开讲react组件之间的一个沟通。那么什么是组件?我知道英文是Component,但这对我而言就是一个单词,毫无意义。要了解Component之间是如何进行友好交流的,那就要先了解Component是个什么鬼。
上回说到的JSX,我们可以这么创建对象:
let element=<h1 className="aaa">A爆了</h1> //等同于 let element=React.createElement( "h1", {className:"aaa"}, "A爆了" )还是老老实实地用h1、div这种标准的HTML标签元素去生成React元素。但是这样的话,我们的JS就会变得巨大无比,全部都是新建的React元素,有可能到时候我们连对象名都不晓得怎么起了,也许就变成let div1;let div2这样的。哈哈哈开个玩笑。但是分离是肯定要分离的。这个时候就有了名为Component的概念。他可以做些什么呢?简单的说就是创建一个个独立的,可复用的小组件。话不多说,我们来瞅瞅来自官方的写法:
写法一:函数型创建组件,大家可以看到我就直接定义一个名为App的方法,每次执行App()的时候就会返回一个新的React元素。而这个方法我们可以称之为组件Component。有些已经上手React的朋友,可能傻了了,这是什么操作,我的高大上class呢?extend呢?很遗憾地告诉你,这也是组件,因为他符合官方定义:1、传入了一个“props” ,2、返回了一个React元素。满足上述两个条件就是Component!
function App(props) { return <span>{props.name}!A爆了</span> }这个是最简易的Component了,在我看来Component本身是对React.createElement的一种封装,他的render方法就相当于React.createElement的功能。高大上的组件功能来啦:
import React, { Component } from 'react'; class App extends Component { render() { return <span>{this.props.name}!A爆了</span> } } export default App;这个class版本的组件和上方纯方法的组件,从React的角度上来说,并无不同,但是!毕竟我class的方式还继承了React.Component,不多点小功能都说不过去对吧?所以说我们这么想继承了React.Component的组件的初始功能要比纯方法return的要多。所以每个React的Component我们都可以当作React元素直接使用。
好了,我们来研究研究Component这个类的方法吧。
首先是一个神奇的constructor函数,这个函数在类中,可以说是用于初始化的函数。如果省去不写,也不会出错,因为我们的组件都是React.Component的子类,所以都继承了React.Component的constructor方法。如果我们在子类Component中定义了constructor相当于是覆盖了父类的方法,这样React.Component的构造函数就失效了。简单地来说就是很多默认的赋值都失效了。你是获取不到props的。因此官方为了提醒大家不要忘记super一下,也就是继承父类的constructor,因此会报"this hasn't been initialised - super() hasn't been called"这个错误。意思就是你先继承一下。也就是说super是执行了父类的constructor的方法。所以!!!重点来了——我们写super的时候不能忘记传入props。不传入props,程序就无法获取定义的组件属性了。
constructor(props) { super(props);//相当于React.Component.call(this,props) }官方也给大家划重点了:
Class components should always call the base constructor with props.(类组建在执行基本constructor的时候,必须和props一起。)
对于我们没有写constructor,但在其他自带方法中,比如render,也可以直接获取到props,这个诡异的操作就可以解释了。因为我们省略了重定义,但是constructor本身不仅是存在的而且也执行了,只不过没有在我们写的子类中体现出来而已。
props的坑