网站还没加载完成时,显示正在加载的画面
对于一些比较大的web项目来说,网站加载较长时,会出现时间长短不一的白屏,想要让用户知道,这个网页是有反应的,给个加载的画面提示,以免损失客户流量,现在以vue
开发的项目为例。
在此之前,希望读者是有了解过vue的,最好是有用过vue的脚手架构建过项目的。
在vue项目中,只有一个html文件,我们要找的就是这个,在vue-cli3
生成的项目中,index.html在public文件夹里。
初始化时的index.html文件是这样的
<!DOCTYPE html>
<html lang="en">
<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, viewport-fit=cover" >
<van-number-keyboard safe-area-inset-bottom />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<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 -->
</body>
</html>
其中<div id="app"></div>
就是整个单页面应用的入口,会在数据加载完才显示,这个时候只要在其上面写上HTML代码就可以在网站还没加载完成时,把自己写的加载动画显示出来了,在网站加载完成时,把自己写的HTML代码移除掉,所以这里需要知道如何才能知道,网站已经加载好了。
主要是利用onreadystatechange
事件,这个稍后再说,先看下添加的h5代码与CSS样式
在<div id="app"></div>
上面添加
<div id="loading">
<div class="div" style="animation: myAnima 1s infinite">
<div class="div1"></div>
<div class="small-black">
<div class="very-small-white"></div>
</div>
<div class="small-white">
<div class="very-small-black"></div>
</div>
</div>
<div class="progress-box margin-top">
<div class="progress"></div>
</div>
<p class="p margin-top">正在玩命加载</p>
</div>
<!-- <div id="app"></div> 添加在上面 -->
接下来是上面H5代码的CSS样式
<style>
#loading{
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#loading .div{
width: 160px;
height: 160px;
background-color: #000000;
position: relative;
border-radius: 50%;
transform: rotate(10deg);
}
#loading .div .div1{
width: 80px;
height: 160px;
background-color: #ffffff;
border-radius: 80px 0 0 80px;
}
#loading .div .small-black{
position: absolute;
bottom: 0;
left: 40px;
width: 80px;
height: 80px;
background-color: #000000;
border-radius: 50%;
}
#loading .div .small-white{
position: absolute;
top: 0;
left: 40px;
width: 80px;
height: 80px;
background-color: #ffffff;
border-radius: 50%;
}
#loading .div .small-black .very-small-white{
position: absolute;
top: 25px;
left: 25px;
width: 30px;
height: 30px;
background-color: #ffffff;
border-radius: 50%;
}
#loading .div .small-white .very-small-black{
position: absolute;
top: 25px;
left: 25px;
width: 30px;
height: 30px;
background-color: #000000;
border-radius: 50%;
}
#loading .margin-top{
margin-top: 20px;
}
#loading .progress-box{
width: 300px;
height: 20px;
border: 1px solid #ababab;
position: relative;
}
#loading .progress-box .progress{
position: absolute;
top: 0;
bottom: 0;
left: 0;
background-color: #1989fa;
width: 0;
}
@keyframes myAnima{
0% {transform: rotate(0deg)}
10% {transform: rotate(36deg)}
20% {transform: rotate(72deg)}
30% {transform: rotate(108deg)}
40% {transform: rotate(144deg)}
50% {transform: rotate(180deg)}
60% {transform: rotate(216deg)}
70% {transform: rotate(252deg)}
80% {transform: rotate(288deg)}
90% {transform: rotate(324deg)}
100% {transform: rotate(360deg)}
}
</style>
最后是js代码,这里要注意的是,这部分代码要放在<head><head>
中,不能放在<body><body>
中,因为只有这样,这部分代码才会在<div id="app"></div>
加载完成之前执行。
<script>
let time = null; // 接收定时器返回的标识
//这个函数用于进度条的变化和文字的变化
function loop(){
let num = parseInt(Math.random()*100);
const progress = document.querySelector('.progress');
progress.style.width = num + '%';
const p = document.querySelector('.p');
p.innerText = '正在玩命加载' + num + '%';
}
//定时器
if(!time){
time = setInterval(()=>{
loop();
}, 100);
}
document.onreadystatechange = completeLoading;
function completeLoading() {
if (document.readyState == "complete") {
clearInterval(time);
time = null;
const loading = document.querySelector('#loading');
loading.remove();
}
}
</script>
好了,主要来看这部分代码
document.onreadystatechange = completeLoading;
function completeLoading() {
if (document.readyState == "complete") {
clearInterval(time);
time = null;
const loading = document.querySelector('#loading');
loading.remove(); //删除元素
}
}
onreadystatechange
这个是ajax的一个事件。
当请求被发送到服务器时,可能有时候需要执行一些事件,每当readyState
改变时,就会触发onreadystatechange
事件。
document.readyState
描述文档的加载状态,有三个值:
-
loading / 正在加载
- document仍在加载
-
interactive / 可交互
- 文档已被解析,”正在加载“状态结束,但是诸如图像,样式表和框架之类的子资源仍在加载。
-
complete / 完成
- 文档和所有子资源已完成加载。表示
load
状态的事件即将被触发。
- 文档和所有子资源已完成加载。表示
当这个属性改变时,就会触发onreadystatechange
事件
当确定加载完成时,就可以让定时器清除定时器了,并且删除用于展示加载动画的元素了
完整代码
<!DOCTYPE html>
<html lang="en">
<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, viewport-fit=cover" >
<van-number-keyboard safe-area-inset-bottom />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<style>
#loading{
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#loading .div{
width: 160px;
height: 160px;
background-color: #000000;
position: relative;
border-radius: 50%;
transform: rotate(10deg);
}
#loading .div .div1{
width: 80px;
height: 160px;
background-color: #ffffff;
border-radius: 80px 0 0 80px;
}
#loading .div .small-black{
position: absolute;
bottom: 0;
left: 40px;
width: 80px;
height: 80px;
background-color: #000000;
border-radius: 50%;
}
#loading .div .small-white{
position: absolute;
top: 0;
left: 40px;
width: 80px;
height: 80px;
background-color: #ffffff;
border-radius: 50%;
}
#loading .div .small-black .very-small-white{
position: absolute;
top: 25px;
left: 25px;
width: 30px;
height: 30px;
background-color: #ffffff;
border-radius: 50%;
}
#loading .div .small-white .very-small-black{
position: absolute;
top: 25px;
left: 25px;
width: 30px;
height: 30px;
background-color: #000000;
border-radius: 50%;
}
#loading .margin-top{
margin-top: 20px;
}
#loading .progress-box{
width: 300px;
height: 20px;
border: 1px solid #ababab;
position: relative;
}
#loading .progress-box .progress{
position: absolute;
top: 0;
bottom: 0;
left: 0;
background-color: #1989fa;
width: 0;
}
@keyframes myAnima{
0% {transform: rotate(0deg)}
10% {transform: rotate(36deg)}
20% {transform: rotate(72deg)}
30% {transform: rotate(108deg)}
40% {transform: rotate(144deg)}
50% {transform: rotate(180deg)}
60% {transform: rotate(216deg)}
70% {transform: rotate(252deg)}
80% {transform: rotate(288deg)}
90% {transform: rotate(324deg)}
100% {transform: rotate(360deg)}
}
</style>
<script>
let time = null;
function loop(){
let num = parseInt(Math.random()*100);
const progress = document.querySelector('.progress');
progress.style.width = num + '%';
const p = document.querySelector('.p');
p.innerText = '正在玩命加载' + num + '%';
}
if(!time){
time = setInterval(()=>{
loop();
}, 100);
}
document.onreadystatechange = completeLoading;
function completeLoading() {
if (document.readyState == "complete") {
clearInterval(time);
time = null;
const loading = document.querySelector('#loading');
loading.remove();
}
}
</script>
</head>
<body>
<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="loading">
<div class="div" style="animation: myAnima 1s infinite">
<div class="div1"></div>
<div class="small-black">
<div class="very-small-white"></div>
</div>
<div class="small-white">
<div class="very-small-black"></div>
</div>
</div>
<div class="progress-box margin-top">
<div class="progress"></div>
</div>
<p class="p margin-top">正在玩命加载</p>
</div>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>