关于react.js:dvaloading使用总结

43次阅读

共计 3581 个字符,预计需要花费 9 分钟才能阅读完成。

在开发异步加载的性能时,为进步用户体验个别会显示加载提醒,最近在应用 umi 做我的项目时接触到dva-loading,对全局和部分组件的异步加载管制还是十分不便的。

在 umi 中应用

装置和配置

装置 npm install dva-loading -S后,进入 src/app.jsdva 进行运行时配置:

import createLoading from "dva-loading"

export const dva = {plugins: [createLoading()]
}

models

models 文件夹下新建 count.js 文件,输出上面内容进行测试:

const delay = (ms)=>new Promise(r=>setTimeout(r,ms))

export default {
    namespace:"count",
    state:{count:1,},
    effects:{*add(action,{put,call}){yield call(delay,1000);
            yield put({type:"change",payload:Math.random()})
        }
    },
    reducers:{change(state,{payload}){return {count:state.count+payload}
        }
    }
}

组件中应用

新建 Count.js 组件进行测试:

import React from "react"
import {connect} from "dva"

function Count({dispatch, count, loading}) {
    
    const isLoading = loading.models.count;
    // 独自对 effects 管制
    // const isLoading = loading.effects["count/add"]
    // 对多个 effects 管制
    // const isLoading = loading.effects["count/add"] || loading.effects["count/minus"] || false;

  return (
    <div>
      {isLoading ? <p> 加载中...</p> : <p>{count}</p>}
      <button onClick={() => dispatch({ type: "count/add"})}>+</button>
    </div>
  )
}

export default connect((state) => ({...state.count, loading: state.loading}))(Count)

dav-loading往全局的 state 中注入了 loading,咱们能够拿到loading 对象判断组件的 model 或者 effect 状态。

dva-loading 源码

dva-loading

const SHOW = '@@DVA_LOADING/SHOW';
const HIDE = '@@DVA_LOADING/HIDE';
const NAMESPACE = 'loading';

function createLoading(opts = {}) {
  const namespace = opts.namespace || NAMESPACE;

  const {only = [], except = []} = opts;
  if (only.length > 0 && except.length > 0) {throw Error('It is ambiguous to configurate `only` and `except` items at the same time.');
  }

  const initialState = {
    global: false,
    models: {},
    effects: {},};

  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: {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;
    },
  };

  function onEffect(effect, { put}, model, actionType) {const { namespace} = model;
    if ((only.length === 0 && except.length === 0) ||
      (only.length > 0 && only.indexOf(actionType) !== -1) ||
      (except.length > 0 && except.indexOf(actionType) === -1)
    ) {return function*(...args) {yield put({ type: SHOW, payload: { namespace, actionType} });
        yield effect(...args);
        yield put({type: HIDE, payload: { namespace, actionType} });
      };
    } else {return effect;}
  }

  return {
    extraReducers,
    onEffect,
  };
}

export default createLoading;

@umijs/plugin-dva 接口实现

@umijs/plugin-dva 抛出的接口 useSelector 能够很不便的帮忙咱们获取数据:

const {loading, count} = useSelector((stores) => ({ 
      loading: stores.loading, 
      count: stores.count 
    }))

通过 useDispatch 获取 dispatch:

const dispatch = useDispatch()
const add = () => dispatch({ type: "count/add"})

批改状态:

import React from "react"
import {useDispatch, useSelector} from "dva"

function Count(props) {const dispatch = useDispatch()
  const add = () => dispatch({ type: "count/add"})

  const {loading, count} = useSelector((stores) => ({ 
      loading: stores.loading, 
      count: stores.count 
    }))
  const isLoading = loading.models.count

  return (
    <div>
      {isLoading ? <p>loading</p> : <p>{count.count}</p>}
      <button onClick={add}>+</button>
    </div>
  )
}

export default Count

全局 loading 管制

通过 useSelector 办法获取的 stores.loading.global,能够获取全局models 的状态是否在 loading 中:

import React from 'react'
const {useSelector} = 'dva'
import {Spin} from 'antd'
const DemoPage = () => {const {loading} = useSelector(stores => ({loading: stores.loading}))
  return (<Spin spinning={loading.global}/>
  )
}

参考:

  • dva-loading
  • @umijs/plugin-dva
  • UmiJS 开发技巧
  • dva-loading 实际用法
  • dva-loading 学习

正文完
 0