随着项目的包越来越大,加载越来越慢,觉得有必要添加一个进度条,最起码让用户知道页面正在加载,而不是卡死了。
进度条用的是NProgress。思路是,NProgress的包使用cdn加载,因为需要尽可能快的显示进度条,所以不能一并打包。在页面进入后就显示进度条,加载后完成进度条。
首先,有两个地方需要有显示进度条的代码。一个是在在index.html中,因为在现在包的过程中加就需要显示进度条。第二个地方是进入每个路由的时候。这个是在PrivateRoute(包裹路由的拦截组件)的componentWillReceiveProps钩子中。
if (nextProps.path !== this.props.path && !NProgress.status) {
NProgress.start()
}
然后,完成进度条的地方。这个地方比较难找。
- 不能在
PrivateRoute中根据子组件是否加载完成判断,因为不知道子组件是否加载完成。 - 不能在
PrivateRoute中根据document.getElementById('root').childElementCount进行判断,原因同上。当然,可以设置一个全局定时器,在定时器中实时判断,但这样并不好。 - 不能通过
dva-loading判断,因为在加载过程中,loading.global会多次变化。 - 不能在
index.js中通过dva的config注入onReducer之类的钩子判断,因为不是所有的页面都有model。 - 最后成功的方法,通过
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()