前言
最近接到一个项目,使用Nuxt.js写了一个网页,但是在加载网页时发生以下情怳:这里用比卡超代替公司logo,也懒得去背,这不是重点(doge)
这样就很不美观,於是增加了Loading动画:
思路
增加div,用css写loading画面,然后使用js进行加载判断。这次就使用document.readyState
来判断网页里的元素是否完全加载完成。
The document.readyState property can return these three string values:
loading: when the document is still loading.
interactive: when the document has finished loading but sub-resources such as stylesheets, images and frames are still loading.
complete: when the document and all sub-resources have finished loading.
当document.readyState !== complete
时,网页未加载完成,把网页的body隠藏,把div显示出来,这时在屏幕显示的是Loading动画;当加载完成时,此时document.readyState === complete
,把div隠藏,把body显示出来。
在Vue.js设定Loading动画
前住public/index.html
代码部分:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>icon.png">
<title><%= htmlWebpackPlugin.options.title %></title>
<style>
body {
margin: 0;
line-height: inherit;
}
*, ::before, ::after {
box-sizing: border-box;
border-width: 0;
border-style: solid;
border-color: #e5e7eb;
}
#loader {
border: 12px solid #f3f3f3;
border-radius: 50%;
border-top: 12px solid #444444;
width: 70px;
height: 70px;
animation: spin 1s linear infinite;
}
@keyframes spin {
100% {
transform: rotate(360deg);
}
}
.center {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
</style>
</head>
<body>
<div id="loader" class="center"></div>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script>
document.onreadystatechange = function() {
if (document.readyState !== "complete") {
document.querySelector(
"body").style.visibility = "hidden";
document.querySelector(
"#loader").style.visibility = "visible";
} else {
document.querySelector(
"#loader").style.display = "none";
document.querySelector(
"body").style.visibility = "visible";
}
};
</script>
</body>
</html>
在Nuxt.js设Loading动画
在项目的根目录下的app.html,没有的话自己建立
代码部分:
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
<style>
#loader {
border: 12px solid #f3f3f3;
border-radius: 50%;
border-top: 12px solid #444444;
width: 70px;
height: 70px;
animation: spin 1s linear infinite;
}
@keyframes spin {
100% {
transform: rotate(360deg);
}
}
.center {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
</style>
</head>
<body {{ BODY_ATTRS }}>
<div id="loader" class="center"></div>
{{ APP }}
<script>
document.onreadystatechange = function() {
if (document.readyState !== "complete") {
document.querySelector(
"body").style.display = "none";
document.querySelector(
"#loader").style.display = "block";
} else {
document.querySelector(
"#loader").style.display = "none";
document.querySelector(
"body").style.display = "block";
}
};
</script>
</body>
</html>
如何测试
有读者可能会有想到说,如果网页加载过快,那就看不到效果了,怎么办?
其实在edge/chrome中,按F12进入主控台,然后选择网络,选择慢速3G
Q&A
我打算把在我在写loading画面时所遇到的问题直接做成Q&A,或许可以解答读者在阅读这篇文章时的疑惑。
Q1: 为什么不直接用Vue的onMounted()
等生命周期钓子来写loading动画?
A1: 这个我试过,不行。Vue加载网页的流程是:首先打开public/index.html,然后在里面加载Vue组件,从最外层判断文档加载状态才好做。如果把loading的div写进Vue文件里的话,会出现了组件正在加载时才开始判断document.readyState
的状态。变相两个都一起加载,从画面上来看就是叠加在一起,然后等onMounted()
结束后判断document.readyState
的事件结束,也就是loading画面已经消息时,页面还在加载,导致loading的div和body出现和消失的时间点不对,效果不成功。
Q2:其实Nuxt.js有.nuxt/views/app.template.html,为什么不直接在里面写loading动画,而是要在项目的根目录下增加app.html?
A2:我这个项目是静态打包的,直接改app.template.html的代码,它并不会打包进来。
Q3:Nuxt.js有.nuxt/layouts/default.vue文件,为什么不直接在里面写loading动画?
A3:它始终是Vue的文件,也是Vue的一部份,并不是最外层,如果在这个文件写loading动画的话会出现和Q1相同的结果。
Q4:其实有人研发了Vue的Loading组件,例如vue-loading-overlay
,为什么不使用它?
A4:
- 不会用,懒得研究
- 不想用,不可能为了一个小小的loading动画而去npm引用一个组件回来
- 根据我的理解,这个可能是给api调用等待数据提交或返回时专门所用的组件,它并没有判断文档加载的功能在里面,逻辑还是要自已写
没理解错的话应该是这样。
资料参考
How to show Page Loading div until the page has finished loading? -- GeeksForGeeks
https://www.geeksforgeeks.org...
Views -- NuxtJS
https://nuxtjs.org/docs/conce...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。