在开发异步加载的性能时,为进步用户体验个别会显示加载提醒,最近在应用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 学习