Redux之旅-1

Redux之旅-1

時(shí)間:2016.4.7-17:24
作者:三月懶驢
入門配置文章:鏈接

準(zhǔn)備

在你的項(xiàng)目下面加入redux / react-redux

    npm install redux --save
    npm install react-redux --save

入門小例子

網(wǎng)上有很多關(guān)于Redux的解析了,我也不從抽象化去講解整個(gè)redux的作用,而發(fā)現(xiàn)講解Redux的編程化例子其實(shí)很少,所以在這里用代碼來說明一下。什么叫做redux,以及它的Action/reducer/store

看過我上一遍項(xiàng)目環(huán)境搭建的朋友應(yīng)該有一個(gè)基本的項(xiàng)目目錄架構(gòu)。
主要寫代碼的還是在app這個(gè)文件夾里面,里面的目錄分布
- component -->放置組件的
- redux -->放置action && reducer
- redux_lesson -->目前是放置用Provider打包出來的組件
- main.js -->程序入口

代碼開始前的思考

我們現(xiàn)在要做一個(gè)很簡(jiǎn)單的東西,用前端的話來說就是一個(gè)div標(biāo)簽,里面放置一個(gè)數(shù)字0,當(dāng)我們點(diǎn)擊這個(gè)div的時(shí)候,里面的數(shù)字就遞增。這里面我們要進(jìn)行一步就是,寫代碼前的思考。
如上所說,我們的需求就是:點(diǎn)擊,數(shù)字遞增。那么我們的一些參數(shù)應(yīng)該定義出來了。

改變View的數(shù)據(jù)—state

個(gè)人簡(jiǎn)單理解的state就是可以反映到view上的可變數(shù)據(jù),這里我們的state定義如下

state = {count:0}

改變state的鑰匙—Action

同樣是個(gè)人理解:state是可變的,但不是隨便的可變,要改變它,就需要一把鑰匙去打開這道大門,而action就是這把鑰匙了
我們把這個(gè)action定義成如下:

increaseAction = {type:'increase'}

Action 本質(zhì)上是 JavaScript普通對(duì)象。我們約定,action內(nèi)使用一個(gè)字符串類型的 type字段來表示將要執(zhí)行的動(dòng)作。多數(shù)情況下,type 會(huì)被定義成字符串常量。

改變state的動(dòng)作—Reducer

個(gè)人的胡亂理解:有了state,有了要改變state的鑰匙Action,那么誰(shuí)來進(jìn)行改變state的操作?reducer就是這么一個(gè)加工車間,你拿著原料(state)和鑰匙(Action)進(jìn)去總車間,用鑰匙(Action)打開對(duì)應(yīng)的生產(chǎn)線,生產(chǎn)出來新的產(chǎn)品(也是state)回去

let reducer = (state={count:0},action)=>{
    //這里面?zhèn)鬟f進(jìn)來兩個(gè)參數(shù),
    //一個(gè)是我們前面定義的state,如果木有傳入的話,就用{count:0}
    //一個(gè)是我們前面定義的action,下面就要檢查它的type來確定操作
    let count = state.count
    switch(action.type){
        //如果鑰匙插對(duì)了孔,我們就返回進(jìn)行了相應(yīng)操作后的state對(duì)象
        case 'increase':
            return {count:count+1}
            break
        //如果鑰匙都不對(duì),就返回沒操作過的state
        default:
            return state
    }
}

被我吃了的store

因?yàn)橄鄬?duì)前面三個(gè)東西來說,store是在太容易理解了,引入官方的話:

Store 就是把它們聯(lián)系到一起的對(duì)象。Redux 應(yīng)用只有一個(gè)單一的 store。當(dāng)需要拆分處理數(shù)據(jù)的邏輯時(shí),使用 reducer 組合 而不是創(chuàng)建多個(gè) store。

開始真正寫代碼了

其實(shí)上面的步驟我們都把一個(gè)redux處理數(shù)據(jù)的相關(guān)工作做的差不多了,那么接下來就是要真正的去寫成程序

創(chuàng)建action

文件位置: app/redux/action.js

export const increaseAction = {type:'increase'}

創(chuàng)建reducer

文件位置: app/redux/reudcer.js

let reducer = (state={count:0},action)=>{
    let count = state.count
    switch(action.type){
        case 'increase':
            return {count:count+1}
            break
        default:
            return state
    }
}
export default reducer

生成store,打包出新組件

重要的事情:store只有一個(gè)!

文件位置: app/redux_lesson/lesson_0.js

'use strict'

import React from 'react'
import { createStore } from 'redux'
import { Provider,connect } from 'react-redux'

//這個(gè)index.js文件會(huì)在在下一步創(chuàng)建
import Index from '../component/index'
import reducers from '../redux/reducer'

//創(chuàng)建store
let store = createStore(reducers)
/*
  mapStateToProps你可以理解成在下面connect的時(shí)候?yàn)榻M件提供一個(gè)props,這個(gè)props的值是redux的state
*/
let mapStateToProps = (state) =>{
    return {count:state.count}
}
//連接你的state和最外層的組件
let Content = connect(mapStateToProps)(Index)

let {Component} = React

//使用Provider來把新的App組件打包出來
class App extends Component{
    render(){
        return <Provider store={store}><Content /></Provider>
    }
}

export default App

創(chuàng)建View

在View里面我們會(huì)接受到兩個(gè)props。一個(gè)是在mapStateToProps生成的state,一個(gè)是store給我們的dispatch,這是是一個(gè)函數(shù),我們用它的方法很簡(jiǎn)單粗暴,往里面?zhèn)魅胍粋€(gè)Action就行了,它接受了這個(gè)Action就會(huì)告訴reducer去執(zhí)行。

文件位置: app/compoment/index.js

'use strict'

import React from 'react'
import { connect } from 'react-redux'
//請(qǐng)注意這里面引入了action
import {increaseAction} from '../redux/action'
let {Component,PropTypes}  = React
class Index extends Component{
    //這一步是檢查傳入的各個(gè)prop類型是否正確
    ProTypes = {
        count:PropTypes.number.isRequired,
    }
    constructor(props){
        super(props)
    }
    handleClick(){
        /*
            這一步輸入this.props可以看到,其實(shí)里面有兩個(gè)東西
            在下面的render里面我們用到了this.props.count這個(gè)
            那么這里我們要用到dispatch
        */
        console.log(this.props)
        let {dispatch} = this.props
        //粗暴簡(jiǎn)單的使用
        dispatch(increaseAction)
    }
    render(){
        let {count} = this.props
        return <div onClick = {this.handleClick.bind(this)}  style={styles.circle}>{count}</div>
    }
}
//樣式文件,不用細(xì)看
let styles = {
    circle:{
        width:'100px',
        height:'100px',
        position:'absolute',
        left:'50%',
        top:'50%',
        margin:'-50px 0 0 -5px',
        borderRadius:'50px',
        fontSize:'60px',
        color:'#545454',
        backgroundColor:'#fcfcfc',
        lineHeight:'100px',
        textAlign:'center',
    }
}
export default Index

進(jìn)一步優(yōu)化代碼

要做一個(gè)點(diǎn)擊遞增就需要那么多步驟是不是很煩惱?但是如果項(xiàng)目大起來之后,你想像這樣,你就可以創(chuàng)建不同的鑰匙Action,再編寫不同的生產(chǎn)線reducer來修改各自的state,但是如上所做,我們的邏輯代碼(點(diǎn)擊遞增)和View還是捆綁在一起(就是在組件里面使用dispatch)這個(gè)方法是不可取的。所以下一步我們就要進(jìn)一步優(yōu)化我們的代碼

文件位置: app/redux_lesson/lesson_0.js

'use strict'

import React from 'react'
import { createStore } from 'redux'
import { Provider,connect } from 'react-redux'

import Index from '../component/index'
import reducers from '../redux/reducer'
/*
    注意:這里是新增的
    相對(duì)原來,我們?cè)谧钔鈱哟虬@里引入Action
*/
import {increaseAction} from '../redux/action'

//創(chuàng)建store
let store = createStore(reducers)
/*
  mapStateToProps你可以理解成在下面connect的時(shí)候提供一個(gè)state
*/
let mapStateToProps = (state) =>{
    return {count:state.count}
}
/*
    注意:這里是新增的
    mapDispatchToProps你可以理解成在下面connect的時(shí)候提供一個(gè)放置好鑰匙的函數(shù)onIncreaseClick,直接調(diào)用就可以去reducer修改state了
*/
let mapDispatchToProps = (dispatch) =>{
    return{onIncreaseClick:()=>dispatch(increaseAction)}
}
/*
    注意:這里是修改了的
    連接你的state和最外層的組件
*/
let Content = connect(mapStateToProps,mapDispatchToProps)(Index)

let {Component} = React

//使用Provider來把新的App組件打包出來
class App extends Component{
    render(){
        return <Provider store={store}><Content /></Provider>
    }
}

export default App

文件位置: app/compoment/index.js

'use strict'

import React from 'react'
import { connect } from 'react-redux'
/*
    注意:這里是修改樂的
    現(xiàn)在不用引入action了,因?yàn)榍耙徊揭呀?jīng)把鑰匙Action放到相應(yīng)的函數(shù)中去,作為props傳入組件里面
*/
//import {increaseAction} from '../redux/action'
let {Component,PropTypes}  = React
class Index extends Component{
    //這一步是檢查傳入的各個(gè)prop類型是否正確
    ProTypes = {
        count:PropTypes.number.isRequired,
        onIncreaseClick:PropTypes.func.isRequired,
    }
    constructor(props){
        super(props)
    }
    handleClick(){
        /*
            注意:這里是修改過的
            現(xiàn)在,我們把打包好的,帶著鑰匙的函數(shù)進(jìn)行調(diào)用
        */
        console.log(this.props)
        let {onIncreaseClick} = this.props
        onIncreaseClick()
    }
    render(){
        let {count} = this.props
        return <div onClick = {this.handleClick.bind(this)}  style={styles.circle}>{count}</div>
    }
}
//樣式文件,不用細(xì)看
...(以下相同就略去)

結(jié)語(yǔ)

redux其實(shí)不難理解,按照我個(gè)人理解的加工工廠模式:有一家大公司叫做store,里面有工廠(reducer),公司(store)只有一家,但這家公司(store)可以有很多工廠(reducer)。要進(jìn)去工廠加工產(chǎn)品(state),就得帶上相應(yīng)得鑰匙(Action),不同的鑰匙(Action)對(duì)應(yīng)工廠中上不同的生產(chǎn)線(redecer里面的switch函數(shù)),從而有不同的產(chǎn)出(改變之后的state)//這個(gè)在下一步創(chuàng)建

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容