关于react.js:dvaloading使用总结

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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理