React Redux簡單實現

設計思想

1.web應用是一個狀態機,試圖與狀態是一一對應的.
2.全部的狀態,保存在一個對象裏.react

基本改變和API

1.Store
Store就是保存數據的地方,你能夠把它當作一個容器,整個應用只能有一個Store.
Redux提供createStore這個函數,用來生成Store.web

import { createStore } from 'redux';
const store = createStore(reducer);
createStore函數接受另外一個reducer函數做爲參數,返回新生成的Store對象.

2.State
State對象包含全部數據,若是想獲得某個時點的數據,就要對Store生成快照,這種時點的數據集合,
就叫作State.當前時刻的State,能夠經過store.getState()拿到.ajax

const state = store.getState();

3.Action
state的變化,會致使view的變化,可是,用戶接觸不到state,只能接觸到view,因此.stated的變化必須是view致使的.Action就是view發出的通知,表示state應該要發生變化了.
Action是一個對象,其中的type屬性是必須的,表示Action的名稱,其餘屬性能夠自由設置.json

const action = {
    type: 'ADD_TODO',
    payload: 'learn Redux'
};

Action的名稱是ADD_TODO,它攜帶的信息是字符串Learn Redux.
能夠這樣理解,Action描述當前發生的事情,改變State的惟一方法,就是使用Action,它會運送數據到Store.redux

4.Action Creator
View要發送多少種信息,就會有多少種Action,能夠定義一個函數生成Action,這個函數就叫ActionCreator.api

const ADD_TODO = '添加 TODO';
function addToDo(text) {
    return {
        type: ADD_TODO,
        text
    }
}

5.store.dispatch()
store.dispatch()是view發出Action的惟一方法.dom

store.dispatch(addTODO('Learn Redux'));

6.reducer
store收到Action之後,必須給出一個新的State,這樣view纔會發生變化.
這種State的計算過程就叫作Reducer.
Reducer是一個函數,他接受Action和當前State做爲參數,返回一個新的State.函數

export default (state = 0, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        case 'getSource':
            return 'bbbb';
        default:
            return 0;
    }
}

reducer函數收到名爲ADD的action之後,就返回一個新的state,做爲加法的計算結果,其餘計算的邏輯,
也能夠根據Action的不一樣來實現.
實際應用中,Reducer函數不用像上面這樣手動調用,store.dispatch方法會觸發Reducer的自動執行.
爲此,Store須要知道Reducer函數,作法就是生成Store的時候,將Reducer傳入createStore方法.fetch

const store = createStore(reducer);

createStore接受Reducer做爲參數,生成一個新的Store.之後每當store.dispatch發送過來一個新的Action,
就會自動調用Reducer,獲得新的State.
7.純函數
Reducer函數最重要的特徵是,它是一個純函數,也就是說,只要是一樣的輸入,必須獲得一樣的輸出.
因爲Reducer是純函數,就能夠保證一樣的State,一定獲得一樣的view,但正由於這一點,Reducer函數裏面不能改變
State,必須返回一個全新的對象.this

return Object.assign({}, state, { thingToChange })
export default (state = 0, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        case 'getSource':
            return 'bbbb';
        case 'ajax':
            return action.data;
        case 'ajaxError':
            return action.data
        default:
            return 0;
    }
}

8.store.subscribe()
Store容許使用store.subscribe方法設置監聽函數,一旦State發生變化,就自定執行這個函數.

store.subscribe(listener);

顯然,只要把view的更新函數(render或this.setState)放入listen,就會實現view的自動渲染.
let unsubscribe= store.subscribe(() => console.log(store.getState()));
unsubscribe();

Store的實現

1.store.getState(),store.dispatch(),store.subscribe()

let { subscribe, dispatch, getState } = createStore(reducer);

Reducer的拆分

Reducer函數負責生成State,因爲整個應用只有一個state對象,包含全部數據,對於大型應用來講,這個State
必然十分龐大,致使Reducer函數也十分龐大.
Redux提供了一個combineReducers方法,用於Reducer的拆分,你只要定義各個子Render函數,
而後用這個方法,將它們合成一個大的Reducer.

import { combineReducers } from 'redux';

const chatReducer = combineReducers({
  chatLog,
  statusMessage,
  userName
})

工做流程

1.用戶發出Action

store.dispatch(action);

2.Store自動調用Reducer,而且傳入兩個參數,當前State和收到的Action.Reducer會返回新的State.

let nextState = todoApp(previousState, action);

3.State一旦有變化,Store就會調用監聽函數.

store.subscribe(listener);

4.listener能夠經過store.getState()獲得當前狀態,若是使用的是React,這時能夠觸發從新渲染view.

function listerner() {
  let newState = store.getState();
  component.setState(newState);   
}

實例

import React, { Component } from 'react';
import { render } from 'react-dom';
import reducer from '../reducers/reducer.js';
import { createStore } from 'redux';

const store = createStore(reducer);

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0,
            source: 'aaaa',
            ajaxSource: 'ajax'
        };
    }
    handleAdd = () => {
        store.dispatch({
            type: 'INCREMENT'
        });
    }
    handleDel = () => {
        store.dispatch({
            type: 'DECREMENT'
        });
    }
    handleGet = () => {
        store.dispatch({
            type: 'getSource'
        })
    }
    handleAjax = () => {
        fetch('../api/response.json')
        .then(response => response.json())
        .then((res) => {
            store.dispatch({
                type: 'ajax',
                data: res
            });
        }).catch((err) => {
            store.dispatch({
                type: 'ajaxError',
                data: err
            });
        })
    }
    render() {
        let _this = this;
        store.subscribe(() => {
            let o = store.getState();
            _this.setState({
                [o.type]: store.getState()[o.type]
            })
        });
        return (
            <div>
                <span>{ this.state.count }</span>
                <button onClick={ this.handleAdd }>add</button>
                <button onClick={ this.handleDel }>del</button>
                <span>{ this.state.source }</span>
                <button onClick={ this.handleGet }>獲取數據</button>
                <span>{ this.state.ajaxSource.res }</span>
                <button onClick={ this.handleAjax }>獲取ajax數據</button>
            </div>
        );
    }
}

render(<App />, document.getElementById('root'));
export default (state = 0, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return Object.assign({}, state, {
                count: state + 1,
                type: 'count'
            });
        case 'DECREMENT':
            return Object.assign({}, state, {
                count: state - 1,
                type: 'count'
            });
        case 'getSource':
            return Object.assign({}, state, {
                source: action.dada,
                type: 'source'
            });
        case 'ajax':
            return Object.assign({}, state, {
                ajaxSource: action.data,
                type: 'ajaxSource'
            })
        case 'ajaxError':
            return Object.assign({}, state, {
                ajaxSource: action.data,
                type: 'ajaxSource'
            });
        default:
            return state
    }
}
相關文章
相關標籤/搜索