如何创建Class组件
ES5方式(已过时)
import React from 'react';const A = React.createClass({render(){return (<div>hi</div>)}})export default A
因为ES5不支持class,才会有这种方式。
ES6方式
import React from 'react';class B extends React.Component {constructor(props){super(props);}render(){return (<div>hi</div>)}}export default B;
以后创建类只用ES6方式,现在还有很多代码是用ES5,即还在搞IE8,如果需要维护就用webpack + babel 将ES6翻译成ES5即可。
Props
作用
- 接受外部数据,且只能读不能写,外部数据由父组件传递。
- 接受外部函数,在恰当的时机,调用该函数,该函数一般是父组件的函数。
事例
Parent父组件:
class Parent extends React.Component {constructor(props){super(props)this.state = {name:'frank} //声明外部数据}onClick = () => {}render(){return <B name={this.state.name} //把外部数据传入到子组件BonClick={this.onClick}>hi</B> //注意,这个this.onClick传给B组件的是一个地址}}
上面的代码里的第八行,外部数据( <B name={this.state.name onClick={this.onClick}>hi</B>} ),被包装成一个对象,如果打印到控制台可以看到 {name:'frank',onClick:...,children:'hi'} ,注意,此处的onClick是一个回调。
B在组件:
class B extends React.Component {constructor(props){super(props);}render(){}}
上面的第1行至第3行是固定代码,其中第2行代码与第3行代码是固定搭配,如果不需要引用外部数据可以不写,但是一旦写了就要补全代码不能漏。
根据上面父组件里“传给B组件的是一个地址”的代码注释提示可知, this.props 是一个外部数据的地址。
如何读取外部数据
通过 this.props.xxx 读取如:
class B extends React.Component {constructor(props){super(props);}render(){return <div onClick={this.props.onClick}>{this.props.name}<div>{this.props.children}</div></div>}}
如何写外部数据
:::danger 禁止写外部数据 :::
理由:这涉及到了React的哲学思想,原则上是应该由数据的主人对数据进行更改!
根据传过来的地址,改外部数据也只会改那个旧的对象的值,并不是新的对象的值,以下代码不推荐:
this.props = {/*另一个对象*/} //改props的值(一个地址)this.props.xxx = 'hi' //改props的属性
既然是外部数据,就不应该从内部改值。
Props的相关钩子
:::tips
钩子是什么?
可以在生命周期执行的函数
:::
componentWillReceiveProps钩子(已被弃用)
作用:当组件接受新的props时,会触发此钩子。
现在已经被弃用,并更改为 UNSAFE_componentWillReceiveProps 总而言之,这个钩子就不用了,只会在维护旧代码才会看到。
State 与 setState
即内部数据
如何初始化State
如下:
class B extends React.Component {constructor(props){super(props);this.state = {user: {name: 'frank', age:19}}}render(){ /*...*/}}
读写内部数据
- 读:用
this.state,如:this.state.xxx.yyy.zzz。 - 写:用
this.setState(???,fn),如this.setState(newState,fn)
如:
class App extends React.PureComponent {constructor(props) {super(props);this.state = {n: 1}}onClick = () => {this.setState(state => ({n: this.state.n + 1})) //写}render(){return (<div>{this.state.n} //读<button onClick={this.onClick}> +1 </button></div>)}}
注:
- 写有两个参数,第二个参数可不写,第二个参数的作用是:在完成写数据的时候就会执行该函数。
- 在
setState时是不会立即改变this.state,会在当前代码运行完成后,才去更新this.state,从而触发UI更新。
根据上面注意的第二条,可以进行改良,不使用对象的形式而是使用函数的形式,如下:
class App extend React.Component {constructor(props){super(props);/*...*/}onClick = () => {this.setState((state) => ({n: this.state.n + 1})) //写}render(){return (/*...*/)}}
这种方式就是,当我想算的时候就会去执行,而不是对象的写法,需要代码运行完成才可以执行。
setState时会 shallow merge
即setState会自动将新state与旧state进行一级合并。
能修改this.state吗
能,但这是不守规矩!如:
this.state.n += 1this.setState(this.state)
并没有人说不可以这样,虽然可以但这只是不遵守规矩的行为,请避免。
