簡述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。

相關文章
相關標籤/搜索