简述React中无状态组件和有状态组件的区别

React中的组件主要分为无状态组件和有状态组件两类。函数

1,无状态组件主要用来定义模板,接收来自父组件props传递过来的数据,使用{props.xxx}的表达式把props塞到模板里面。无状态组件应该保持模板的纯粹性,以便于组件复用。建立无状态组件以下:this

var Header = (props) = (
    <div>{props.xxx}</div>
);

2,有状态组件主要用来定义交互逻辑和业务数据(若是用了Redux,能够把业务数据抽离出去统一管理),使用{this.state.xxx}的表达式把业务数据挂载到容器组件的实例上(有状态组件也能够叫作容器组件,无状态组件也能够叫作展现组件),而后传递props到展现组件,展现组件接收到props,把props塞到模板里面。建立有状态组件以下:spa

class Home extends React.Component {
    constructor(props) {
        super(props);
    };
    render() {
        return (
            <Header/>  //也能够写成<Header></Header>
        )
    }
}

这个是官方默认的写法,在构造函数里面默认要传递一个参数进去,而且要调用super()方法,来获取子类的实例。可是比较疑惑的地方是为何要传递这些参数,传递这些参数有什么用?code

由于从render()里面的组件来看,构造函数不传递参数也能够获取到组件实例上的props属性。以下:blog

class Home extends React.Component {
    constructor() {
        super();
    };
    render (){
        return(
            <div>
                <Header name="俺是子组件实例上props属性"/>
            </div>
        );
    };
};

class Header extends React.Component {
    constructor() {
        super();
    };
    render() {
        return (
            <div>{this.props.name}</div>  //构造函数中并无传递props属性,这里经过{this.props.name}依然获取到了值
        );
    };
};

这个比较好理解,由于render()方法是子组件原型上的方法,获取实例属性的时候要经过this来访问,若是去掉this就获取不到了。图片

那问题来了,若是咱们要在构造函数中访问props改怎么办呢?此时,咱们就要在constructor构造函数中传递一个props参数,这样就能够访问到子组件实例上的props属性了。以下:文档

class Header extends React.Component {
    constructor(props) {
        super();
        this.name = props.name;  //获取到子组件实例上的props.name属性,赋值给实例属性name
    };
    render() {
        return (
            <div>{this.name}</div>
        );
    };
};

还有一个问题,super(props)方法中为何也要传递一个props属性呢?看下面的例子:原型

class Header extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            nameOne: props.name,
            nameTwo: this.props.name  //super()方法中传递了props属性,this.props才能够获取到name属性
        }
    };
    render() {
        return (
            <div>{this.state.nameOne}{this.state.nameTwo}</div>
        );
    };
};

其实,props.name和this.props.name的值都是同样的,可是它俩仍是有区别的,props.name中这个props就是子组件的属性props,可是this.props.name中的这个props却不是子组件的属性props,虽然值都是同样的,这个props其实在调用super方法的时候被传递到了Component这个父类中去了,因此this.props.name获取到的是Component父类中的props属性。看下React的源码:源码

图片描述

发现没,子类super方法把props参数传递给了父类Component,Component把props参数挂载到它的实例属性props上了。因此,你只有给super方法中传递props参数,在构造函数里才能用this,props.xxxit

若是super方法中不传递props参数,获取this.props.name的值就会报错。获取this.props显示为undifined:以下:

class Header extends React.Component {
    constructor(props) {
        super();
        this.state = {
            nameOne: this.props.name, 
            nameTwo: this.props  
        };
        console.log(this.props.name);  //报错
        console.log(this.props);  //undifined
    };
    render() {
        return (
            <div>{this.state.nameOne}{this.state.nameTwo}</div>
        );
    };
};

这种写法本质是给子组件Header的实例属性state.nameOne和state.nameTwo赋值了一个子组件Header的实例属性props,简单来讲,就是Header子组件建立了一个state属性,而后又把本身的props属性赋值给了本身的state属性。
为何this.props打印出undefined?由于props是调用子组件的时候传入的参数,因此在构造函数内部是访问不到props的,那么对于this.props.name来讲,毫无疑问确定报错。

因此,对与构造函数中的props参数和super中的props参数来讲,若是你不在构造函数中用this.props和props,彻底能够不用传参。反之就要传参。可是对于this.props和props来讲获取到的值都是同样的,因此写哪一个均可以。可是官方文档上是两个参数都有写。因此为了严谨,仍是都写上吧。

可是,我我的仍是喜欢这样的写法。

constructor(props) {
    super(props);
    this.state = {
        name: props.name
    }
};

不加this的是value,加了this的是key。

相关文章
相关标签/搜索