redux實現原理

redux基本概念

基本概念

1.store
用來保存數據的地方,使用createStore來生成數據
store = createStore(fn)

2.state,經過拷貝store中的數據獲得
state = store.getState()

3.action,用來表示視圖發生的變化
action = {
    type:'ADD_TODO',
    payload:'Learn Redux'
}

4.Action Creator 用來生成action
const ADD_TODO = '添加 TODO'

function addTodo(text){
    return {
        type:ADD_TODO,
        text
    }
}

5.dispatch 用來發出action
store.dispatch(addTodo('Learn Redux'));

6.reducer 用來處理action,返回新的state
const reducer = function(state,action){
    return new_state
}

createStore

function createStore(reducer,initState,enhancer){
    
    //0.接收state,添加觀察者
    let state = initState
    let listeners = []
    
    //1. 獲取state
    function getState(){
        return JSON.parse(JSON.stringify(state))
    }
    
    //2.造一個dispatch來發送action
    function dispatch(action){
        state = reducer(state,action)
        listeners.forEach(linstener => linstener())
    }
    
    //3.添加訂閱者
    function subscribe(listener){
        listeners.push(listener)
        return function(){
            listeners.filter(item => item != listener)
        }
    }
    
    return {
        getState,
        dispatch,
        subscribe
    }
}

combineReducer

//先拿到reducer
function combineReducer(reducer){
    //把state和action交給reducer處理
    return (state={},action) => (
        //拿到對應reducer的處理結果在把原來的屬性拷貝到新對象上
        Object.keys(reducer).reduce((cur,key) => {
            cur[key] = reducer[key](state[key],action)
            return cur
        },{})
    )
}

bindActionsCreators

function bindActionsCreators(actions,dispatch){
    //先拿到actions和dispatch
    return Object.keys(actions).reduce((obj,key)=>{
        obj[key] = function(){
            //等執行的時候在調用真正的actions和dispatch
           dispatch(actions[key].apply(null,arguments)) 
        }
        return obj
    },{})
}

ApplyMiddleware

image

1.在action以後redecer處理以前

中間件的執行過程

image

const middleware (dispatch) => (
    (action) => {
        console.log('middleware')
        dispatch(action)
        console.log('after middleware')
    }
)

const middleware1 (dispatch) => (
    (action) => {
        console.log('middleware1')
        dispatch(action)
        console.log('after middleware1')
    }
)

// middleware -> middleware1 -> action -> middleware1 -> middleware

compose函數的虹吸現象

image

//先執行棧頂的middleware而後迴流到棧底的middleware
const compose = (middlewares) => (
    middlewares.reduce((a,b) => (
        (...args) => a(b(...args))
    ))
)

中間件的實現

const middleware1 = dispatch => (
    action => {
        console.log('middleware1')
        let res = dispatch(action)
        console.log('after middleware1')
        return res
    }
)
const middleware2 = dispatch => (
    action => {
        console.log('middleware2')
        let res = dispatch(action)
        console.log('after middleware2')
        return res
    }
)

const middleware3 = dispatch => (
    action => {
        console.log('middleware3')
        let res = dispatch(action)
        console.log('after middleware3')
        return res
    }
)

let middlewares = [middleware1,middleware2,middleware3]

const compose = middlewares => middlewares.reduce((a,b) => (
    (...args) => a(b(...args))
))

const dispatch = (action) => {
    console.log(`action: ${action}`)
    return action
}

//這是最後一箇中間件,調用它將返回第一個中間件
const afterDispatch = compose(middlewares)(dispatch)

const testAction = args => ({
    type:"ACTION_TEST",
    args
})

afterDispatch(testAction('plus!'))

applyMiddleware

const compose = middlewares => middlewares.reduce((a,b) => (
    (...args) => a(b(...args))
))


//1.接收中間件
export default function applyMiddleware(...middlewares){
    //2.接收store方法
    return function(createStore){
        //3.接收reducer
        return function(reducer){
            let store = createStore(reducer)
            let dispatch 
            let middlewareAPI = {
                getState:store.getState,
                dispatch:action => dispatch(action)
            }
            //把state和dispatch方法傳給中間件的一個函數
            middlewares = middlewares.map(middleware => middleware(middlewareAPI))
            //將dispatch傳入中間件,把dispatch傳給最後一箇中間件,把最後一箇中間件的第2個函數傳給上一個函數,虹吸
            dispatch = compose(...middlewares)(store.dispatch)
            return {
                ...store,
                dispatch //先執行middleware1
            }
        }
    }
}

react-redux

Provider

class Provider extends React.Component{
//靜態屬性childContextTypes聲明提供給子組件的Context對象的屬性,並實現一個實例getChildContext方法,返回一個表明Context的純對象 (plain object) 。
    static childContextTypes = {
        store:propTypes.object.isRequired
    }
    getChildContext(){
        return {
            store:this.props.store
        }
    }
    render(){
        return this.props.children
    }
}

Connect

function Connect(mapStateToProps,mapDispatchToProps){
    return function(WrapedComponent){
        class ProxyComponent extends React.Component {
        //子組件須要經過一個靜態屬性contextTypes聲明後,才能訪問父組件Context對象的屬性,不然,即便屬性名沒寫錯,拿到的對象也是undefined。
            static contextTypes = {
                store:propTypes.object
            }
            constructor(props,context){
                super(props,context)
                this.store = context.store
                   //初始化state
                this.state = mapStateToProps(
                    this.store.getState()
                )
            }
            componentWillMount(){
            //當state發生變化的時候經過setState更新組件的變化
                this.unsubscribe = this.store.subscribe(()=>{
                this.setState(mapStateToProps(this.store.getState()));
              });
            }
             componentWillUnmount(){
             //當組件刪除的時候取消監聽state的變化
              this.unsubscribe();
            }
            render(){
               let actions = {}
               if(typeof mapDispatchToProps == 'function'){
                actions = mapDispatchToProps(this.store.disaptch);
              }else if(typeof mapDispatchToProps == 'object'){
                actions = bindActionCreators(mapDispatchToProps,this.store.dispatch);
              }
              return <WrapedComponent {...this.state} {...actions}/>
            }
        }
        return ProxyComponent
    }
}
相關文章
相關標籤/搜索