对于一些比较大的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>

版权声明:本文为tourey-fatty原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/tourey-fatty/p/12465683.html