zoukankan      html  css  js  c++  java
  • Redux

    1、数据流

    image

    2、redux的实现

    const createStore = (reducer) => {
        let state = {};
        let listeners = [];
    
        const getState = () => state;
    
        const dispatch = (action) => (reducer) => {
            state = reducer(state, action);
            listeners.forEach(fn => fn());
        }
    
        let subscribe = (listener) => {
            listeners.push(listener);
        }
        //初始的状态
        dispatch({type: '@@CHEN-REDUX});
        return { getState, dispatch, subscribe }
    }
    
    export {createStore} ;
    

    3、context的使用

    在生命周期方法中引用 Context
    如果 contextTypes 在组件中定义,下列的生命周期方法将接受一个额外的参数, context 对象:

    • constructor(props, context)
    • componentWillReceiveProps(nextProps, nextContext)
    • shouldComponentUpdate(nextProps, nextState, nextContext)
    • componentWillUpdate(nextProps, nextState, nextContext)
    • componentDidUpdate(prevProps, prevState, prevContext)
    • function(props, context)

    childContextTypes中声明类型要不不能用 getChildContext 中取

    4、react-redux的实现

    Provider 利用context属性可以让所有的子组件来取到store

    // render(
    //     <Provider store={store}>
    //       <App />
    //     </Provider>,
    //     document.getElementById('root')
    //   )
    
    export class Provider extends React.Component {
        static childContextTypes = {
            store:PropTypes.object
        }
        constructor(props, context) {
            super(props, context);
            this.store = props.store;
        }
    
        getChildContext() {
            return {store: this.store}
        }
    
        render() {
            return this.props.children;
        }
    }
    

    connet 的实现

    import React, {PropTypes} from 'react';
    
    //高阶组件
    //1.负责接收一个组件,把state里的数据放进去,返回一个组件
    //2.数据变化的时候,能够通知组件
    
    function bindActionCreator (creators, dispatch) {
        return (...args) => dispatch(creator(...args));
    }
    
    function bindActionCreators (creators, dispatch) {
        let bound = {};
        Object.keys(creators).forEach(v=>{
            let creator = creators[v]
            bound[v] = bindActionCreator(creator, dispatch)
        })
        return bound;
    }
    
    export const connect = (mapStateToProps = state => state, 
        mapDispatchToProps = {}) => (WrapComponent) => {
        return class ConnectComponent extends React.Component {
            static contextTypes = {
                store: PropTypes.object
            }
            constructor(props, context) {
                super(props, context);
                this.state = {
                    props: {}
                }
            }
    
            componentDidMount() {
                const {store} = this.context;
                store.subscribe(()=>this.update());
                this.update();
            }
    
            update() {
                const {store} = this.context;
                //把state传入mapStateToProps,然后返回自己需要的
                const stateProps = mapStateToProps(store.getState());
                //方法不能直接给,需要dispatch  直接执行addGun()是没有意义的。
                //需要addGun = store.dispatch(addGun 才有意义
                const dispatchProps = bindActionCreators(mapDispatchToProps, store.dispatch)
                this.setState({
                    props: {
                        ...this.state.props,
                        ...stateProps,
                        ...dispatchProps
                    }
                    
                })
            }
    
            render() {
                return <WrapComponent {...this.state.props} />
            }
        }
    };
    
    
    

    5、中间件

    中间件的理解

    只有发送 Action 的这个步骤,即store.dispatch()方法,可以添加功能

    举例来说,要添加日志功能,把 Action 和 State 打印出来,可以对store.dispatch进行如下改造。

    let next = store.dispatch;
    store.dispatch = function dispatchAndLog(action) {
      console.log('dispatching', action);
      next(action);
      console.log('next state', store.getState());
    }
    

    对store.dispatch进行了重定义,在发送 Action 前后添加了打印功能。这就是中间件的雏形。

    中间件就是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,

    中间件的使用
    const store = createStore(
      reducer,
      initial_state,
      applyMiddleware(logger)
    );
    
    applyMiddlewares() 的实现单个
    const createStore = (reducer, enhancer) => {
        if (enhancer) {
            return enhander(createStore)(reducer);
        }
        let state = {};
        let listeners = [];
    
        const getState = () => state;
    
        const dispatch = (action) => (reducer) => {
            state = reducer(state, action);
            listeners.forEach(fn => fn());
        }
    
        let subscribe = (listener) => {
            listeners.push(listener);
        }
    
        dispatch({});
        return { getState, dispatch, subscribe }
    }
    
    
    export function applyMiddleware (middleware) {
        return createStore=>(...args)=>{
            const store = createStore(...args);
            let dispatch = store.dispatch;
    
            const midApi = {
                getState: store.getState,
                dispatch: (...args) => dispatch(...args)
            }
            dispatch = middleware(midApi)(store.dispatch);
            return {
                ...store,
                dispatch
            }
        }
    }
    

    多个中间件

    export default function applyMiddleware(...middlewares) {
      return (createStore) => (reducer, preloadedState, enhancer) => {
        var store = createStore(reducer, preloadedState, enhancer);
        var dispatch = store.dispatch;
        var chain = [];
    
        var middlewareAPI = {
          getState: store.getState,
          dispatch: (action) => dispatch(action)
        };
        chain = middlewares.map(middleware => middleware(middlewareAPI));
        dispatch = compose(...chain)(store.dispatch);
    
        return {...store, dispatch}
      }
    }
    

    compose

    export function compose (...funcs) {
        if (funcs.length == 0) {
            return arg => arg;
        }
        if (funcs.length == 1) {
            return funcs[0]
        }
        return funcs.reduce((ret, item) => (...args) => ret(item(...item)))
    }
    
    compost(f1, f2, f3)
    
    f1(f2(f3()))
    
    自己实现一个thunk 感觉就是处理异步的callback
    
    const thunk = ({dispatch, getState})=>next=>action=> {
        if (typeof action == 'function') {
            return action(dispatch, getState);
        }
        return next(actions);
    }
    
    export default thunk;
    
    

    使用传入的是active

    store.dispatch(function(dispatch){
                setTimeout(function(){
                    dispatch({type: 'INCREMENT'})
                }, 5000)
            })
    

    理解

    const thunk = function({dispatch, getState}){
        return function (next) { //dispatch = middleware(midApi)(store.dispatch);
            return function (action) {
                if (typeof action == 'function') {
                    return action(dispatch, getState);
                }
                return next(actions);
            } 
        }
    }
    
    let next = store.dispatch;
    store.dispatch = function dispatchAndLog(action) {
      console.log('dispatching', action);
      next(action);
      console.log('next state', store.getState());
    }
    

    多个连续异步

    store.dispatch(function(dispatch){
                setTimeout(function(){
                    console.log('1')
                    dispatch(function(dispatch) {
                        setTimeout(function () {
                            console.log('2')
                            dispatch({type: 'INCREMENT'})
                        }, 2000)
                    }) 
                    
                }, 1000)
            })
            console.log('0')
    
    redux-promise的源码,就会明白它内部是怎么操作的
    export default function promiseMiddleware({ dispatch }) {
      return next => action => {
        if (!isFSA(action)) {
          return isPromise(action)
            ? action.then(dispatch)
            : next(action);
        }
    
        return isPromise(action.payload)
          ? action.payload.then(
              result => dispatch({ ...action, payload: result }),
              error => {
                dispatch({ ...action, payload: error, error: true });
                return Promise.reject(error);
              }
            )
          : next(action);
      };
    }
    

    如果 Action 本身是一个 Promise,它 resolve 以后的值应该是一个 Action 对象,会被dispatch方法送出(action.then(dispatch)),但 reject 以后不会有任何动作;如果 Action 对象的payload属性是一个 Promise 对象,那么无论 resolve 和 reject,dispatch方法都会发出 Action。

    使用有两种方式:

    第一种穿promise然后返回action

    store.dispatch(
        new Promise((resolve, reject)=> {
                    setTimeout(()=> {
                        console.log(1);
                        resolve('sss')
                    }, 2000)
                }).then(response => { return {
                    type: 'INCREMENT',
                    payload: response
                  }})
            )
    

    一种是在把传入的active的payload生成promise

    store.dispatch(
            {
                type:'INCREMENT',
                payload: new Promise((resolve, reject)=> {
                    setTimeout(()=> {
                        console.log(1);
                        resolve('sss')
                    }, 2000)
                }).then(function(data) {
                    return data;
                })
            }
        )
    
  • 相关阅读:
    《JAVA设计模式》中的代理模式Proxy
    《JAVA设计模式》中的外观模式Facade
    《JAVA设计模式》中的组合模式Composite
    《JAVA设计模式》中的享元模式Flyweight
    《JAVA设计模式》中的策略模式Strategy
    《JAVA设计模式》中的模板模式Template
    《JAVA设计模式》中的观察者模式Observer
    《JAVA设计模式》中的迭代器模式Iterator
    《JAVA设计模式》中的责任链模式Chain of Responsibility
    面对对象编程
  • 原文地址:https://www.cnblogs.com/chenjinxinlove/p/8467727.html
Copyright © 2011-2022 走看看