Redux學習之我對於其工做流程的理解和實踐

目錄

1 工做流程圖

2 各部位職責

3 Demo

1 工做流程圖

2 各部位職責

我在理解這個流程圖的時候,採用的是一種容易記住的辦法,而且貼切實際工做職責。
咱們能夠把整個Redux工做流程理解成一個圖書館中借書操做。css

  • React Components(借書的人)
  • Action Creators (借書的實際操做)
  • Store (圖書館管理員)
  • Reducer (借書記錄本)

所以當咱們理解了每一個部位的身份後,咱們就按照着上面工做流程圖一塊兒來屢一下整個過程。首先借書的人(React Component)發起一個借書的實際操做(Action Creators)傳達(dispatch)一個(action)給圖書館管理員(Store),圖書館管理員須要查閱借書小本本(Reducer),查閱完之後圖書館就能從借書小本本中獲取到返回(return)的信息,再告訴借書的人「OK,我在借書小本本我登記好了,書你能夠拿走了」,這樣借書的人(React Component)就拿走書了。react

是否是如今有點印象對於整個工做流程?chrome

3 Demo

(說了這麼多,不練下怎麼知道爽不爽呢?)
npm

3.1 功能介紹

咱們要實現的功能很簡單,就是經過redux去管理數據,數據[1, 2, 3]這時候都是從reducer中取出來的。
redux

3.2 項目中的React Componet

主要展現兩個分別爲index.js和todoList.js數組

  • index.js
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';

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

話很少說!瀏覽器

  • todoList.js
import React,  { Component } from 'react';
import 'antd/dist/antd.css';
import { Input, Button, List } from 'antd';
import store from './store'; // 等價於 import store from './store/index.js' 
import { getInputChangeAction, getAddItemAction, getDeleteitemAction } from './store/actionCreator';

class TodoList extends Component {
    
    constructor(props) {
        super(props);
        this.state = store.getState();
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        this.handleBtnClick = this.handleBtnClick.bind(this);
        store.subscribe(this.handleStoreChange); //store中的數據只要被改變,就會自動觸發裏面的動做
    }

    render() {
        return (
            <div style={{marginTop: '10px', marginleft: '10px'}}>  
                <div>
                    <Input 
                        value={this.state.inputValue} 
                        placeholder='todo info' 
                        style={{width: '500px', marginRight: "10px"} } 
                        onChange={this.handleInputChange}
                    >
                    </Input>
                    <Button type="primary" onClick={this.handleBtnClick}>提交</Button>
                </div>
                <List
                    style={{marginTop: '10px', width: '500px'}}
                    bordered
                    dataSource={ this.state.list }
                    renderItem={ (item, index) => (<List.Item onClick={this.handleItemDelete.bind(this, index)}> {item} </List.Item>) }
                >    
                </List>
            
            </div>   
        )
    }

    handleInputChange(e) {
        /* 
        原代碼,現將action封裝到一個獨立的actionCreator.js中 便於維護 
        const action = {
            type: CHANGE_INPUT_VALUE,
            value: e.target.value
        }
        */
        const action = getInputChangeAction(e.target.value);
        store.dispatch(action)
    }

    handleStoreChange() {
        this.setState(store.getState());
    }

    handleBtnClick() {
        const action = getAddItemAction();
        store.dispatch(action);
    }

    handleItemDelete(index) {
        const action = getDeleteitemAction(index);
        store.dispatch(action);
    }

}

export default TodoList;

簡單說兩句上述代碼。
1).渲染一個輸入框一個按鈕,點擊按鈕,將輸入框中的數據發送store中並更改list的值,而後組件會接收到store數據變動將新數據渲染。
2).點擊列表中的每一項會刪除該項。其實就是組件發送一個action給store,告訴它,刪掉我點的!
antd

3.3 首先安裝redux

npm install redux --save--dev

3.4 重點開場,建立store文件夾

store文件總共有四個文件分別以下
dom

  • index.js 在這個文件中建立store
// index.js

import { createStore } from 'redux';
import reducer from './reducer';

const store = createStore(
    reducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);  

export default store;

簡單解釋兩句以上代碼,從redux中引入一個createStore方法,經過這個方法傳入咱們的小本本reducer,建立一個store。那麼問題來了,第二個參數這麼一長條是啥玩意?莫慌兄dei~咱們爲了更好的管理數據經過使用redux去管理,那麼chrome有一個Redux Devtools插件能夠可視化redux數據。而這一長條就是爲了告訴瀏覽器,據說你有redux可視化數據的插件?還不快給老子顯示一下redux數據!
異步

  • actionCreator.js
    還記得它的功能嗎?(借書的實際操做!)所以,這個文件中存放的就是咱們操做數據時的全部action。
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes';

export const getInputChangeAction = (value) => ({
    type: CHANGE_INPUT_VALUE,
    value
});

export const getAddItemAction = () => ({
    type: ADD_TODO_ITEM
});

export const getDeleteitemAction = (index) => ({
    type: DELETE_TODO_ITEM,
    index
});

1).簡單說兩句上面的代碼,就是導出了三個得到action的方法,由於咱們用redux去管理數據的一個目的就是,咱們不在把業務邏輯放在React Component中,而是全封裝在一個actionCreator中。而後咱們就能夠在React Componet中直接引入actionCreator,而後吊用其中暴露的接口便可得到一個action,而後再把這個action派發給reducer。

2).那麼再說兩句action,在redux中action是一個對象,這個對象中有一個參數是type,記錄的就是一個咱們須要怎樣的操做(換句話說就是這是一個怎樣的action),當咱們記錄了這個type的時候,咱們就能夠在reducer小本本中根據咱們所須要的type從而如何去改變store中的數據;其action這個對象中別的參數能夠是咱們作這個操做時須要的別的value。

  • actionTypes.js
// actionTypes.js

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';

簡單說兩句上述代碼,這個文件實際上是對action中的type進行封裝成一個常量。這樣作的目的是:若是是一個普通字符串,當咱們在一個項目中屢次拼寫的時候極可能會一個字符沒拼對而出bug,而這個bug咱們還有可能花一天的時間去找,最後你可能會

有童鞋可能會說,我都複製還不行嗎!行!累不累?可是,既然要用redux去管理數據,咱們就一勞永逸吧!

  • reducer.js 、
    說了這麼久的小本本,終於到它了!很少說,上代碼!
&emsp;
//reducer.js
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes';

const defaultState = {
    inputValue: '123',
    list: [1, 2, 3]
};

export default (state = defaultState, action) => {
    // 更改input輸入框的值
    if (action.type === CHANGE_INPUT_VALUE) {
        const newState = JSON.parse(JSON.stringify(state)); //深拷貝
        newState.inputValue = action.value;
        return newState;
    }
    // 將input提交的值插入到數組list中
    if (action.type === ADD_TODO_ITEM) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.push(newState.inputValue);
        newState.inputValue = '';
        console.log(newState);
        return newState;
    }
    //刪除item
    if (action.type === DELETE_TODO_ITEM) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index, 1);
        return newState;
    }
    return state;
}

老規矩,講代碼!
1.一般咱們定義倉庫的一個默認值defaultState。
2.咱們導出一個方法。這個方法作的事情就是先記錄不一樣的action.type執行不一樣的操做,返回給store對應操做後的數據。

總結:
當React Component須要執行一個操做時,就會調用actionCreator暴露的接口得到一個action,而後將這個action去dispatch給store,store拿到這樣一個action就會去查小本本,而後根據小本本預先設定好的操做執行並返回對應的結果給store,而後store中的數據就會改變。咱們一般在React Component的constructor初始化時,執行store.subscribe(this.handleStoreChange)。表示的是,當store數據變化時,就會觸發裏面的操做拿到最新的數據。

後續會繼續更新
1.redux-thunk,這個插件使得action除了對象外還能夠是一個函數,這樣咱們能夠將一個異步請求,從react組件中封裝到store中的actionCreator進行管理。
2.redux-immutable ,這個插件使得store中的數據成爲一個immutable不可變對象
3.react-redux,鏈接父子組件的store,使得父組件中引入了store後,如何在子組件中鏈接並使用這個store

----------------做者的話:若是你看到了這裏,那說明你真的是一個棒棒噠,第一次發博,碼文碼字還不是特別專業,不過會慢慢進步的,若有不對的地方,還請你們指點一下!--------------

相關文章
相關標籤/搜索