• 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;
                })
            }
        )
    
  • 相关阅读:
    【原创】绝对居中
    MSSQL数据库各角色权限
    如何升级至 XHTML?
    XHTML 语法
    5.4 删除一个元素节点或者文本节点
    Ajax实现无刷新的获取数据并绑定到GridView,以及无刷新更新数据[转]
    鼠标滑过时显示图片内容隐藏和鼠标滑过图片隐藏内容显示的两种小方法
    纯CSS3魔方的制作
    201920201学期 20192415 《网络空间安全专业导论》XOR加密
    201920201学期 20192415 《网络空间安全专业导论》第四周学习总结
  • 原文地址:https://www.cnblogs.com/chenjinxinlove/p/8467727.html
Copyright © 2020-2023  润新知