1. 程式人生 > >react and redux(一)props和state

react and redux(一)props和state

  • 安裝
  • 示例
  • 總結

安裝

  1. 安裝好node.js和npm之後,命令列執行下面的命令:
npm install --global create-react-app
  1. 建立應用目錄:
create-react-app first_react_app //first_react_app為應用名
  1. 在應用目錄下:
npm start

啟動之後瀏覽器會自動開啟頁面:http://localhost:3000/

應用的入口是src/index.js檔案。發現渲染的元件是App,對應App.js檔案中的元件。

示例

修改index.js如下:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import ClickCounter from './ClickCounter';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(<ClickCounter />, document.getElementById('root'));
registerServiceWorker();

這樣應用啟動後加載的元件就是ClickCounter這個元件了,這個元件實現對應的ClickCounter.js檔案如下:

import React,{Component} from 'react';
export default class ClickCounter extends Component{

    constructor(props){
        super(props);
        this.onClickButton = this.onClickButton.bind(this);
        this.state={count:0};
    }

    onClickButton(){
        this
.setState({count:this.state.count+1}); } render(){ return ( <div> <button onClick={this.onClickButton}>Click Me</button> <div> Click Count:{this.state.count} </div> </div> ); } }

啟動應用後,點選按鈕,計數器自動加1。

下面是上面這個例子的加強版,實現自定義元件的相互巢狀。
父元件的程式碼如下:

import React,{Component} from 'react';
import Counter from './Counter';
export default class ControlPanel extends Component{
    render(){
        return(
            <div>
                <Counter caption="First" initValue={0}/>
                <Counter caption="Second" initValue={10}/>
                <Counter caption="Third" initValue={20}/>
            </div>
        )
    }
}

其中父元件內部呼叫了子元件Counter,並傳給它兩個prop,一個是caption,一個是initValue,其中由於catpion屬性是字串,可以被JSX語法直接識別,而initValue是數字,由於JSX語法中,非字串的屬性賦值時需要用{}的形式才能正確賦值,所以以{0}這種方式。
下面是Counter元件的程式碼:

import React,{Component} from 'react';
export default class Counter extends Component{
    constructor(props){
        super(props);

        this.onClickIncrementButton=this.onClickIncrementButton.bind(this);
        this.onClickDecrementButton=this.onClickDecrementButton.bind(this);

        this.state = {
            count: props.initValue || 0
        }
    }

    onClickIncrementButton(){
        this.setState({count:this.state.count+1});
    }

    onClickDecrementButton(){
        this.setState({count:this.state.count-1});
    }

    render(){
        const {caption} = this.props;
        return (
            <div>
                <button  onClick={this.onClickIncrementButton}>+</button>
                <button  onClick={this.onClickDecrementButton}>-</button>
                <span>{caption} count:{this.state.count}</span>
            </div>
        );
    }
}

由上可見,傳入的屬性cation只是用於顯示,initValue只是用於設定元件內部state的初值,然後又加了可以給count這個內部state加1和減1的按鈕,以及最終將count這個state顯示。

總結

  1. 本次的例子大致講解了props和state的使用範圍。props適用於元件外向元件內傳參,而state只是在元件內部使用。
  2. 元件內修改state的值不能直接使用this.state.count=this.state.count+1;這種方式,因為這種方式只是野蠻地修改了state,卻沒有驅動元件進行重新渲染,所以並沒有變化;而使用this.setState()函式首先改變this.state的值,然後驅動元件經歷更新過程,介面上才會變化。
  3. 元件的建構函式中為什麼要加上這兩句話?
this.onClickIncrementButton=this.onClickIncrementButton.bind(this);
this.onClickDecrementButton=this.onClickDecrementButton.bind(this);

答:在ES6的語法中,類的每個成員函式在執行時的this並不是和類例項自動繫結的。而在建構函式中,this就是當前元件例項,所以為了將來在成員函式內部使用方便,在建構函式中將這個例項的特定函式繫結this為當前例項。這兩條語句的作用,就是通過bind方法讓當前例項中兩個函式被呼叫時,函式內部的this始終指向當前元件例項。