Redux and middleware to realize ideas from zero

First, why should redux

vue react and to manage data flow is unidirectional state. The communication between the two components is relatively non-father and son in trouble, especially in the communications between the components across multiple stages. Therefore, the two frames has a corresponding state manager, such as a redux vuex mobx other outstanding frame. Of which the general design idea is to publish a subscription model by managing storage containers need to share data, central management of multiple distributed solve the pain points of cross-level communication. After reading redux source, understanding the deep, to write himself one.
Reference article:
https://www.jianshu.com/p/e984206553c2
https://github.com/bricksert/blog/issues/22

Second, when to use redux

Ruan Yifeng teacher's blog Redux introductory tutorial (a) which says:
no need to use Redux scene:
the user is very simple to use
no collaboration between users
do not need a lot of interaction with the server did not use WebSocket
view layer (View) only obtain from a single source of data
need to use redux scenario:
the user's use of complex
identity of the different users have different use (for example, ordinary users and administrators)
can collaborate between multiple users
a lot of interaction with the server, or use the WebSocket
View acquiring data from multiple sources

III. Specific realization

Version 1: publish and subscribe model

counterReducer = function (state, action) {
    switch (action.type) {
        case 'INCREAMENT':
            return {
                ...state,
                count: state.count + 1
            };
        case 'DECREAMENT':
            return {
                ...state,
                count: state.count - 1
            };
        default:   // 没有匹配的action,则返回原来的state
            return state
    }
}
const createStore = function (reducer, initState) {
    let listeners = [];
    state = initState;
    function subscribe(listener) { 
        listeners.push(listener);
    }
    function dispatch(action) {
        state = reducer(state, action);
        listeners.forEach(listener => {  // 执行所有subscrible的回调方法
            listener();
        })
    }
    function getState() {
        return state;
    }
    return {
        subscribe,
        dispatch,
        getState
    }
}

1. The use of local state is a state monitor
2. action.type restraining, if a corresponding reducer, then modify, if not modified without

// 使用redux_v1
const store = createStore(counterReducer,{
    count: 20
})
store.subscribe(() => {
    console.log(store.getState())
})
store.dispatch({
    type: 'INCREAMENT'
})
store.dispatch({   // dispatch一个不存在的action,state并不会改变
    type: 'SET_PRICE',
    price: 111
})

For a version of it, reducer plan is a function that takes the old state, scheduled to return to the new state. The project must have multiple state, each state requires a corresponding reducer. And the state can not all write together when creating the store. We must reducer and state split, you can always add a new state and reducer.

Version two: Split reducer and state

const bookInit = {
    name: '小葵花妈妈课堂',
    price: 20
}
function bookReducer(state, action) {
    if (!state) {  // 若不存在,则将state赋值
        state = bookInit
    }
    switch (action.type) {
        case 'SET_NAME':
            return {
                ...state,
                name: action.name
            };
        case 'SET_PRICE':
            return {
                ...state,
                price: action.price
            };
        default:
            return state
    }
}
const counterInit = {
    count: 10
}
function counterReducer(state, action) {
    if (!state) {
        state = counterInit
    }
    switch (action.type) {
        case 'INCREAMENT':
            return {
                ...state,
                count: state.count + 1
            };
        case 'DECREAMENT':
            return {
                ...state,
                count: state.count - 1
            };
        default:
            return state
    }
}
function combineReducer(reducers) {  // 拆分redux核心
    const reducerKeys = Object.keys(reducers);
    return function combination(state, action) {
        let nextState = {}
        for (let i = 0; i < reducerKeys.length; i++) {
            let key = reducerKeys[i];
            let reducer = reducers[key];
            let prevState = state[key];
            nextState[key] = reducer(prevState, action);
        }
        return nextState;
    }
}
const createStore = function (reducer, initState = {}) {
    let listeners = [];
    state = initState;
    function subscribe(listener) {
      	  listeners.push(listener);
	      return function unsubscribe() {  // 退订
	      const index = listeners.indexOf(listener)
	      listeners.splice(index, 1)
	    }
    }
    function dispatch(action) {
        state = reducer(state, action);
        listeners.forEach(listener => {
            listener();
        })
    }
    function getState() {
        return state;
    } 
    dispatch({  // 在创建store是dispatch一个不匹配任何 type 的 action。其目的是获取初始值
        type: Symbol() // 标识唯一性
    })
    return {
        subscribe,
        dispatch,
        getState
    }
}

So that we achieved a 7788 redux, which is the core combineReducer achieve. You can take a closer look.

const reducer = combineReducer({
    counter: counterReducer,
    book: bookReducer
})
const store = createStore(reducer)  // 不给初始值,让其获取
unsubscribe = store.subscribe(() => {
    console.log(store.getState())
})
store.dispatch({
    type: 'INCREAMENT'
})
unsubscribe() // 退订后下面的dispatch不会执行回调
store.dispatch({
    type: 'SET_PRICE',
    price: 200
})

IV. Middleware thought

What is middleware?
Personally think that the middleware that can be woven into the program, regardless of the business logic of reusable components. It is used to provide additional functionality.

For example, now there is a demand in each modification state when the state recorded before the amendment, why amended, as well as state modified. Implement a logging component, directly on the code

const reducer = combineReducer({
    counter: counterReducer,
    book: bookReducer
})
const store = createStore(reducer) // 不给初始值
unsubscribe = store.subscribe(() => {
   // todo
})
const next = store.dispatch;
store.dispatch = function (action) {
    console.log('action:',JSON.stringify(action), )
    console.log('修改前:',store.getState(), )
    next(action);
    console.log('修改后:',store.getState(), )
    console.log('---------------------------------------')
}
store.dispatch({
    type: 'INCREAMENT'
})

store.dispatch({
    type: 'SET_PRICE',
    price: 18
})

Here Insert Picture Description

Published 51 original articles · won praise 18 · views 40000 +

Guess you like

Origin blog.csdn.net/weixin_42565137/article/details/103538562