天天看點

【前端】react and redux教程學習實踐,淺顯易懂的實踐學習方法。

前言

  前幾天,我在博文

【前端】一步一步使用webpack+react+scss腳手架重構項目

 中搭建了一個react開發環境。然而在實際的開發過程中,或者是在對源碼的了解中,感受到react中用的最多的,就是redux了,于是打開文檔學習了一番。在這裡做一些記錄。

redux概念

  redux是什麼?它是用來管理狀态的。在react開發中,我們經常會遇到一種情況,元件與父元件之間的通信,元件與元件之間的通信,

其中元件與父元件的通信通過props來完成。

  

/***********parent****************/
<Number
            value={this.state.number}
        />

/***********number****************/
<div >{this.props.value}</div>      

number内部使用props擷取父元件自己的state,通過setState更改父元件的state.number可以實作number元件的實時更新。

那麼元件與元件之間的通信呢?例如我們有a,b兩個元件,現在a要給b轉發一個激活狀态active,一般思路是,在同一個父元件下,使用props傳遞回調函數的方式。

/*********元件 a**********/
class A{
    .....
    changeActive(){
        this.props.changebActive();
    }
    render(){
        return <button onClick={this.changeActive}></button>
    }
}
/*********元件 b**********/
class B{
    render(){
        return <div>狀态:{this.props.active}</div>
    }
}
/*********元件 parent**********/
class parent{
    ......
    changebActive(){
        this.setState({
            active:"開啟"
        })
    }
    render(){
        return <div>
                <A
                    changebActive={this.changebActive.bind(this)}
                />
                <B
                    active={this.state.active}
                />
            </div>
    }
}      

通過A點選調用到parent的 changebActive方法,設定state更新b,這種方式非常容易使項目變得不可預測,并且state管理複雜,沒錯,redux很大程度就是用來解決這個問題的,它在react中的思想是:

将元件狀态統一放到同一個超級父元件,再由這個超級父元件用更專業的方法分發props給所有的子元件,無論嵌套多少層。由超級父元件統一管理應用中所有的state。

---這就是redux。無論api名詞如何晦澀難懂,它的核心思想是在開發中浮現的。

redux的API

  一、所有的狀态,儲存在一個對象裡面。

    所有的狀态都儲存在一個對象裡面,redux基本三大原則之一,單一資料源,一個應用所有的狀态被儲存在一個對象裡,這個對象通過store管理,想象一下,整個頁面的狀态被存儲在一個對象裡面,其實類似一個配置檔案,你可以從伺服器讀取,可以從任何地方改變。view則是同步的,這看起來更精煉不是麼。

  二、store

  Store 就是儲存狀态資料對象的地方,你可以把它看成一個容器。整個應用隻能有一個 Store。

Redux 提供

createStore

這個函數,用來生成 Store。createStore傳入了一個函數這個函數将接收到兩個參數,一個state,一個action,action就是由子元件發出的更改請求,state就是那個單一的state對象。

import { createStore } from 'redux';
const store = createStore(fn);      

  三、action

發起狀态改變的起點是action,由子元件發出action,子元件通過props調用回調函數,通知父元件發出action。

觸發:

store.dispatch(action);      

  四、store.dispatch

  這個方法就是發出action的方法,一般傳入action,調用這個方法之後,會觸發在createStore中傳入的函數。

  五、store.getState

   它用來擷取目前的state對象

  六、reducer

這個就是createStore中傳入的函數的名詞解釋,這個函數的執行必須傳回一個新的state:

export default (state={number:0},action)=>{//每次調用都會傳入state和目前通知的action
    switch(action.type){
        case "NUMBER_ADD": //發過來的action如果是NUMBER_ADD 就傳回number++
            state.number++;
        break;
        case "NUMBER_LESS":
            state.number--;
        break;
    }
    return Object.assign({},state); //必須傳回一個新的state ,可以使用assign合并 
}      

注意這裡用了es6,給state添加了一個預設值,{number:0}。

  六、store.subscribe()

 Store 允許使用

store.subscribe

方法設定監聽函數,一旦 State 發生變化,就自動執行這個函數。

import { createStore } from 'redux';
const store = createStore(reducer);

store.subscribe(render);      

比如上面我在生成store傳入reducer函數之後,使用store.subscribe()設定監聽函數為render,則每次state改變了,就會執行render函數,重新整理視圖。

概念名詞太多,不如實踐

  實踐一個number輸入框的加減元件,你就能大概知道redux究竟是怎麼工作的。

  一、準備

    首先你需要搭建一個react的開發環境,需要一個index.html 輸出目錄等。詳見我的另一篇博文:

  。

然後你需要一定的react開發實踐,React有props和state兩個屬性: props意味着父元件分發下來的屬性,state意味着元件内部可以自行管理的狀态,并且整個React沒有資料向上回溯的能力,也就是說資料隻能單向向下分發,或者自行内部消化。

了解這個是了解React和Redux的前提。

  你需要npm安裝redux:

    num install redux react-redux --save-dev

  二、代碼

  1.number.js

   

import React,{Component} from "react";

const propTypes = {
    add:React.PropTypes.func.isRequired,
    less:React.PropTypes.func.isRequired,
    value:React.PropTypes.object.isRequired
}
class Number extends Component{
    add(){
        this.props.add({type:"NUMBER_ADD"}) //調用app.js中傳過來的箭頭函數,傳入了type為NUMBER_ADD的action
    }
    less(){
        this.props.less({type:"NUMBER_LESS"})
    }
    render(){
        return <div>
                    <input type="text" value={this.props.value.number}/>
                    <button onClick={this.add.bind(this)}>
                        +
                    </button>
                    <button onClick={this.less.bind(this)}>
                    -
                    </button>
                </div>
    }
}
Number.propTypes = propTypes;
export {Number};      

注意那兩個click回調,發出了action,以及那個this.props.value.number的引用,props傳入了state,擷取了state.number

2.app.js

import React from "react";
import ReactDOM from "react-dom";

import {createStore} from "redux"; //導入createStore 

import {Number} from "./number.js";  
import reducers from "./reducers.js";    
const store = createStore(reducers); //生成store

const content = document.querySelector(".content");
const render = ()=> ReactDOM.render(
    <div>
        <Number
            value={store.getState()}
            add={(action)=>store.dispatch(action)}  //傳入一個函數,傳入發送過來的action,由reducers處理之後傳回state,
            less={(action)=>store.dispatch(action)}
        />
    </div>,
    content
);
render();
store.subscribe(render); //在reducers處理之後,傳回了state,然後觸發了render,更新視圖      

3.reducers.js

export default (state={number:0},action)=>{//每次調用都會傳入state和目前通知的action
    switch(action.type){
        case "NUMBER_ADD": //發過來的action如果是NUMBER_ADD 就傳回number++
            state.number++;
        break;
        case "NUMBER_LESS":
            state.number--;
        break;
    }
    return Object.assign({},state); //必須傳回一個新的state ,可以使用assign合并 
}      

這就是createStore傳入的函數,當發出action,store會自動調用它傳入state,action 傳回了一個新的state.

Redux 的基本用法就介紹到這裡,下一篇介紹它的進階用法:中間件和異步操作。為什麼是下一篇?因為我也還沒學。

資源

阮一峰的教程 number——demo的github 知乎上大神對redux的易懂解讀

--------------------------------

轉載必須在頁頭注明出處,此前多文章被轉載不署名,自重

========================================================

轉載請注明出處。

繼續閱讀