網站還沒加載完成時,顯示正在加載的畫面


對於一些比較大的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" >
    <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" >
    <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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM