Redux基础

const Redux = require('redux');

const reducer = function(state, action) {
    if (action.type === 'changeName') {
        // const newState = JSON.parse(JSON.stringify(state));
     // 不能直接修改原来的state对象
return Object.assign({}, state, {name: action.name}); } else { // 未配置情况,返回原来的state return state; } } // 参数: reducer(return state), [init state] const store = Redux.createStore(reducer, {name: 'init name', age: 20}); // 订阅监听 store.subscribe(() => console.log(store.getState())); // 同步dispatch const action = {
  changeName() {
    return {   type:
'changeName',   name: 'lily'
    }
  },
  increment (number) {
      return {
        type: "increment",
        data: number
      }
    }
  }
 store.dispatch(action);

redux中, Redux API主要有:

1. createStore()

2. applyMiddleware()

3. combineReducers()

// combineReducers 实现原理
// 将各个reducer函数包裹在一个对象中,最后通过生成一个新reducer函数 
// function combineReducers(reducers) {
//     return function reducer(state, action) {
//         let newState = {};
//         for (let key in reducers) {
//           把state中每一个属性值作为state,带入对应的Reducer中进行处理
//             newState[key] = reducers[key](state[key],action);
//         }
//     }
// }
const Redux = require('redux');

// const state = { a: [], b: [], c:{ name: '', group: []} };

const aReducer = function(state, action) {
    if (typeof state === 'undefined') return [];
    switch (action.type) {
        case 'a':
            return state.concat([action.data]);
        default:
            return state;
    }
}

const bReducer = function(state, action) {
    if (typeof state === 'undefined') return [];
    switch (action.type) {
        case 'b':
            return state.concat([action.data]);
        default:
            return state;
    }
}

const cNameReducer = function(state, action) {
    if (typeof state == 'undefined') return '';
    switch (action.type) {
        case 'c':
            return action.name;
        default:
            return state;       
    }
}

const cGroupReducer = function(state, action) {
    // state对应的是group的value
    if (typeof state === 'undefined') return [];
    switch(action.type) {
        case 'c':
            return state.concat(action.item);
        default:
            return state;
    }
}

const cReducer = function (state, action) {
    // state对应的是c的value
    if (typeof state === 'undefined') return {name: '', group: []};
    switch(action.type) {
        case 'c':
            // 返回reducer处理函数,然后调用
            return Redux.combineReducers({name: cNameReducer, group: cGroupReducer})(state, action); 
        default:
            return state;
    }
}
// 每个属性对应的reducer
const reducers = Redux.combineReducers({a: aReducer, b: bReducer, c: cReducer});
const store = Redux.createStore(reducers, {a: [111], b: [222], c:{ name: 'hi', group:[] }});

store.subscribe(() => console.log(store.getState()));

const action1 = {
    type: 'b',
    data: 'lead'
};
const action2 = {
    type: 'a',
    data: 'tail'
}
const action3 = {
    type: 'c',
    name: 'jkp',
    item: 'pp'
}
store.dispatch(action1);
store.dispatch(action2);
store.dispatch(action3);

 

store API包括以下几个:

1. getState()

2. subscribe(callback)

3. dispatch(action)

Redux默认只支持同步action[返回对象](即:dispatch本身只能进行同步触发),若要实现异步action,需要借助一些特殊的插件,如redux-thunk,redux-promise。

let action = {
// 同步action,返回一个对象
  increment (number) {
    return {
      type: "increment",
      data: number
    }
  },

// 异步action, 返回一个函数
  asyncIncrement (number) {
    return dispatch => {
      // 函数内部执行异步操作
      setTimeout(() => {
      // dispatch一个同部的action对象
        dispatch({
          type: "increment",
          data: number
        })
      }, 1000);
    }
  },
}

与此同时,在createStore()加入第二个参数--中间件 Redux.applyMiddleware(xxx)

const thunk = require("redux-thunk").default;

const store = Redux.createStore(reducer, Redux.applyMiddleware(thunk));

 

这里提一下‘redux-thunk'这个中间件的使用[转自:https://juejin.im/post/6844903505199628301]

    import { createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk';
    import rootReducer from './reducers/index';
    //注册thunk到applyMiddleware
    const createStoreWithMiddleware = applyMiddleware(
      thunk
    )(createStore);
    
    const store = createStoreWithMiddleware(rootReducer);
    
    //action方法
    function increment() {
      return {
        type: INCREMENT_COUNTER
      };
    }
    //执行一个异步的dispatch
    function incrementAsync() {
      return dispatch => {
        setTimeout(() => {
          dispatch(increment());
        }, 1000);
      };
    }

源码分析

// thunk-redux 源码
    function createThunkMiddleware(extraArgument) {
     // 将dispatch和getState传入action,next()和action()是redux提供的方法。
      return ({ dispatch, getState }) => next => action => {
       // 接着做判断,如果action是一个function,就返回action(dispatch, getState, extraArgument),否则返回next(action)
        if (typeof action === 'function') {
          return action(dispatch, getState, extraArgument);
        }
    
        return next(action);
      };
    }
const thunk = createThunkMiddleware(); // 给thunk设置一个属性withExtraArgument,并且将createThunkMiddleware整个函数赋给它。 thunk.withExtraArgument = createThunkMiddleware; export default thunk;

总结:thunk是一个中间函数,它的返回值是一个函数表达式。action里面可能传递多个参数,我们不可能再专门替每个action写一个传递方法。那么就有了thunk的出现,thunk可以将多个参数的函数作为一个参数传递。

例如有这样一个action

function test(arg1, arg2, ...) {
      return {
            type: "TEST",
            arg1,
            arg2,
            ...
      }
 }

然后我们在执行dispatch()方法是,需要把test()的返回值作为参数传递。这样就解决了多参数传递的问题,这个test()就成了一个thunk。

 

 promise实现异步触发

// 借助promise实现异步触发
function callAction() {
    const actionPromise = new Promise((resovle, reject) => {
        const action = {
            type: 'changeName',
            name: 'lily'
        };
        resovle(action);
    })

    actionPromise.then((action) => {
        store.dispatch(action);
    })
}
callAction();

PS: redux-devtools下载安装  https://github.com/zalmoxisus/redux-devtools-extension/releases

然后在项目目录下npm i redux-devtools-extension --save-dev

import {composeWithDevTools} from 'redux-devtools-extension';

const store = Redux.createStore(reducer, composeWithDevTools(Redux.applyMiddleware(thunk)));

 

posted @ 2020-03-01 10:25  cecelia  阅读(153)  评论(0编辑  收藏  举报