Redux之旅-1

時間:2016.4.7-17:24
做者:三月懶驢
入門配置文章:連接javascript

準備

在你的項目下面加入redux / react-redux前端

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

入門小例子

網上有不少關於Redux的解析了,我也不從抽象化去講解整個redux的做用,而發現講解Redux的編程化例子其實不多,因此在這裏用代碼來講明一下。什麼叫作redux,以及它的Action/reducer/storejava

看過我上一遍項目環境搭建的朋友應該有一個基本的項目目錄架構。react

主要寫代碼的仍是在app這個文件夾裏面,裏面的目錄分佈npm

- component -->放置組件的
   - redux     -->放置action && reducer
   - redux_lesson -->目前是放置用Provider打包出來的組件
   - main.js   -->程序入口

代碼開始前的思考

咱們如今要作一個很簡單的東西,用前端的話來講就是一個div標籤,裏面放置一個數字0,當咱們點擊這個div的時候,裏面的數字就遞增。這裏面咱們要進行一步就是,寫代碼前的思考。
如上所說,咱們的需求就是:點擊,數字遞增。那麼咱們的一些參數應該定義出來了。編程

改變View的數據—state

我的簡單理解的state就是能夠反映到view上的可變數據,這裏咱們的state定義以下redux

state = {count:0}

改變state的鑰匙—Action

一樣是我的理解:state是可變的,但不是隨便的可變,要改變它,就須要一把鑰匙去打開這道大門,而action就是這把鑰匙了
咱們把這個action定義成以下:segmentfault

increaseAction = {type:'increase'}

Action 本質上是 JavaScript普通對象。咱們約定,action內使用一個字符串類型的 type字段來表示將要執行的動做。多數狀況下,type 會被定義成字符串常量。架構

改變state的動做—Reducer

我的的胡亂理解:有了state,有了要改變state的鑰匙Action,那麼誰來進行改變state的操做?reducer就是這麼一個加工車間,你拿着原料(state)和鑰匙(Action)進去總車間,用鑰匙(Action)打開對應的生產線,生產出來新的產品(也是state)回去app

let reducer = (state={count:0},action)=>{
    //這裏面傳遞進來兩個參數,
    //一個是咱們前面定義的state,若是木有傳入的話,就用{count:0}
    //一個是咱們前面定義的action,下面就要檢查它的type來肯定操做
    let count = state.count
    switch(action.type){
        //若是鑰匙插對了孔,咱們就返回進行了相應操做後的state對象
        case 'increase':
            return {count:count+1}
            break
        //若是鑰匙都不對,就返回沒操做過的state
        default:
            return state
    }
}

被我吃了的store

由於相對前面三個東西來講,store是在太容易理解了,引入官方的話:

Store 就是把它們聯繫到一塊兒的對象。Redux 應用只有一個單一的 store。當須要拆分處理數據的邏輯時,使用 reducer 組合 而不是建立多個 store。

開始真正寫代碼了

其實上面的步驟咱們都把一個redux處理數據的相關工做作的差很少了,那麼接下來就是要真正的去寫成程序

建立action

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

export const increaseAction = {type:'increase'}

建立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只有一個!

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

'use strict'

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

//這個index.js文件會在在下一步建立
import Index from '../component/index'
import reducers from '../redux/reducer'

//建立store
let store = createStore(reducers)
/*
  mapStateToProps你能夠理解成在下面connect的時候爲組件提供一個props,這個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

建立View

在View裏面咱們會接受到兩個props。一個是在mapStateToProps生成的state,一個是store給咱們的dispatch,這是是一個函數,咱們用它的方法很簡單粗暴,往裏面傳入一個Action就好了,它接受了這個Action就會告訴reducer去執行。

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

'use strict'

import React from 'react'
import { connect } from 'react-redux'
//請注意這裏面引入了action
import {increaseAction} from '../redux/action'
let {Component,PropTypes}  = React
class Index extends Component{
    //這一步是檢查傳入的各個prop類型是否正確
    ProTypes = {
        count:PropTypes.number.isRequired,
    }
    constructor(props){
        super(props)
    }
    handleClick(){
        /*
            這一步輸入this.props能夠看到,其實裏面有兩個東西
            在下面的render裏面咱們用到了this.props.count這個
            那麼這裏咱們要用到dispatch
        */
        console.log(this.props)
        let {dispatch} = this.props
        //粗暴簡單的使用
        dispatch(increaseAction)
    }
    render(){
        let {count} = this.props
        return <div onClick = {this.handleClick.bind(this)}  style={styles.circle}>{count}</div>
    }
}
//樣式文件,不用細看
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

進一步優化代碼

要作一個點擊遞增就須要那麼多步驟是否是很煩惱?可是若是項目大起來以後,你想像這樣,你就能夠建立不一樣的鑰匙Action,再編寫不一樣的生產線reducer來修改各自的state,可是如上所作,咱們的邏輯代碼(點擊遞增)和View仍是捆綁在一塊兒(就是在組件裏面使用dispatch)這個方法是不可取的。因此下一步咱們就要進一步優化咱們的代碼

文件位置: 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'
/*
    注意:這裏是新增的
    相對原來,咱們在最外層打包這裏引入Action
*/
import {increaseAction} from '../redux/action'

//建立store
let store = createStore(reducers)
/*
  mapStateToProps你能夠理解成在下面connect的時候提供一個state
*/
let mapStateToProps = (state) =>{
    return {count:state.count}
}
/*
    注意:這裏是新增的
    mapDispatchToProps你能夠理解成在下面connect的時候提供一個放置好鑰匙的函數onIncreaseClick,直接調用就能夠去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'
/*
    注意:這裏是修改樂的
    如今不用引入action了,由於前一步已經把鑰匙Action放到相應的函數中去,做爲props傳入組件裏面
*/
//import {increaseAction} from '../redux/action'
let {Component,PropTypes}  = React
class Index extends Component{
    //這一步是檢查傳入的各個prop類型是否正確
    ProTypes = {
        count:PropTypes.number.isRequired,
        onIncreaseClick:PropTypes.func.isRequired,
    }
    constructor(props){
        super(props)
    }
    handleClick(){
        /*
            注意:這裏是修改過的
            如今,咱們把打包好的,帶着鑰匙的函數進行調用
        */
        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>
    }
}
//樣式文件,不用細看
...(如下相同就略去)

結語

redux其實不難理解,按照我我的理解的加工工廠模式:有一家大公司叫作store,裏面有工廠(reducer),公司(store)只有一家,但這家公司(store)能夠有不少工廠(reducer)。要進去工廠加工產品(state),就得帶上相應得鑰匙(Action),不一樣的鑰匙(Action)對應工廠中上不一樣的生產線(redecer裏面的switch函數),從而有不一樣的產出(改變以後的state)

相關文章
相關標籤/搜索