yuxino / source

🌟 The source code analysis
3 stars 0 forks source link

Dva-Loading 用法以及源码分析 #2

Open yuxino opened 6 years ago

yuxino commented 6 years ago

Dva-Loading 是一个处理Effect的插件。不过在Dva里面插件被理解为是一个Hook。因为Dva-Loading的文档解释的非常的不详细,于是看了一下源码,才恍然大雾。

Dva-loading通过extraReducersonEffect两个Hook来给原来的Model加上了一个全局的loading还有局部的loading以及处理HideShow的Reducers。原理是给每个Effects执行开始的时候和执行结束的时候加上一个Action。大概看起来代码会是这样子。

function onEffect(effect, { put }, model, actionType) {
  // 省略 ...
  return function*(...args) {
      yield put({ type: SHOW, payload: { namespace, actionType } });
      yield effect(...args);
      yield put({ type: HIDE, payload: { namespace, actionType } });
  };
}

SHOWHIDE会在extraReducers里面被处理。

const extraReducers = {
  [namespace](state = initialState, { type, payload }) {
    const { namespace, actionType } = payload || {};
    let ret;
    switch (type) {
      case SHOW:
        ret = {
          ...state,
          global: true,
          models: { ...state.models, [namespace]: true },
          effects: { ...state.effects, [actionType]: true },
        };
        break;
      case HIDE: // eslint-disable-line
        const effects = { ...state.effects, [actionType]: false };
        const models = {
          ...state.models,
          [namespace]: Object.keys(effects).some((actionType) => {
            const _namespace = actionType.split('/')[0];
            if (_namespace !== namespace) return false;
            return effects[actionType];
          }),
        };
        const global = Object.keys(models).some((namespace) => {
          return models[namespace];
        });
        ret = {
          ...state,
          global,
          models,
          effects,
        };
        break;
      default:
        ret = state;
        break;
    }
    return ret;
  },
};

global会在有请求的时候被设置。其他的model下的loading会在请求执行的时候被设置为true。effects是指定actionType的loading状态。