react dva 项目添加进度条–NProgress

随着项目的包越来越大,加载越来越慢,觉得有必要添加一个进度条,最起码让用户知道页面正在加载,而不是卡死了。

进度条用的是NProgress。思路是,NProgress的包使用cdn加载,因为需要尽可能快的显示进度条,所以不能一并打包。在页面进入后就显示进度条,加载后完成进度条。

首先,有两个地方需要有显示进度条的代码。一个是在在index.html中,因为在现在包的过程中加就需要显示进度条。第二个地方是进入每个路由的时候。这个是在PrivateRoute(包裹路由的拦截组件)的componentWillReceiveProps钩子中。

if (nextProps.path !== this.props.path && !NProgress.status) {
  NProgress.start()
}

然后,完成进度条的地方。这个地方比较难找。

  1. 不能在PrivateRoute中根据子组件是否加载完成判断,因为不知道子组件是否加载完成。
  2. 不能在PrivateRoute中根据document.getElementById('root').childElementCount进行判断,原因同上。当然,可以设置一个全局定时器,在定时器中实时判断,但这样并不好。
  3. 不能通过dva-loading判断,因为在加载过程中,loading.global会多次变化。
  4. 不能在index.js中通过dvaconfig注入onReducer之类的钩子判断,因为不是所有的页面都有model
  5. 最后成功的方法,通过MutationObserver进行DOM监听。不过,这个监听是在index.js中,不在PrivateRoute中,不知道为什么,在路由拦截组件里监听会不完整。
// index.js
// 监听 #root 元素--以实现页面加载完成后取消 NProgress 进度条
// 不放到 PrivateRoute 里面,是因为在那里监听不完全,原因未知
function observeRoot() {
  if (!supportMutationObserver) {
    console.log('浏览器不支持DOM监听')
    return
  }
  const targetNode = document.body
  const config = { childList: true, subtree: true, characterData: true }
  const callback = () => {
    let root = document.getElementById('root') || {}
    if (NProgress.status && root.childElementCount) {
      NProgress.done()
    }
  }

  let observer = new MutationObserver(callback)
  observer.observe(targetNode, config)
}

observeRoot()