Back

H5首屏加载

需求:移动端h5套壳应用,在启动app与进入h5页面之间有几秒白屏时间,需在此处添加loading动画。

出现白屏,是因为打包后 JS 和 CSS 文件比较大,还未加载完成,但index.html会较快加载,可以在该文件里添加动画。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
<style>
	  #loading-mask {
        position: fixed;
        left: 0;
        top: 0;
        height: 100%;
        width: 100%;
        background: #fff;
        user-select: none;
        z-index: 9999;
        overflow: hidden
      }     
      .loading-wrapper {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -100%);
        text-align: center;
      }
      .loading-dot {
        animation: antRotate 1.2s infinite linear;
        transform: rotate(45deg);
        position: relative;
        display: inline-block;
        font-size: 64px;
        width: 45px;
        height: 45px;
        box-sizing: border-box
      }
      .loading-dot i {
        width: 22px;
        height: 22px;
        position: absolute;
        display: block;
        background-color: #EF621D;
        border-radius: 100%;
        transform: scale(.75);
        transform-origin: 50% 50%;
        opacity: .3;
        animation: antSpinMove 1s infinite linear alternate
      }
      .loading-dot i:nth-child(1) {
        top: 0;
        left: 0
      }
      .loading-dot i:nth-child(2) {
        top: 0;
        right: 0;
        -webkit-animation-delay: .4s;
        animation-delay: .4s
      }
      .loading-dot i:nth-child(3) {
        right: 0;
        bottom: 0;
        -webkit-animation-delay: .8s;
        animation-delay: .8s
      }
      .loading-dot i:nth-child(4) {
        bottom: 0;
        left: 0;
        -webkit-animation-delay: 1.2s;
        animation-delay: 1.2s
      }
      .loading-text{
        color: #EF621D;
        font-size: 16px;
        width: 150px;
        margin-top: 23px;
      }
      @keyframes antRotate {
        to {
          -webkit-transform: rotate(405deg);
          transform: rotate(405deg)
        }
      }
      @-webkit-keyframes antRotate {
        to {
          -webkit-transform: rotate(405deg);
          transform: rotate(405deg)
        }
      }
      @keyframes antSpinMove {
        to {
          opacity: 1
        }
      }
      @-webkit-keyframes antSpinMove {
        to {
          opacity: 1
        }
      }
</style>

<body>
	<div id="app">
		<div id="loading-mask">
		    <div class="loading-wrapper">
		        <span class="loading-dot loading-dot-spin"><i></i><i></i><i></i><i></i></span>
			    <div class="loading-text">正在加载</div>
		    </div>
	    </div>
    </div>
</body>

在#app里添加loading元素,当Vue实例挂载到<div id="app">元素上时,Vue会将该元素作为根节点,并用Vue组件中的模板内容替换掉原来的内容。 这样做在web端和安卓端都没有问题。但ios依然白屏,没有loading动画,如果把最外层的div#app元素去掉,ios可以显示加载动画(当然这样加载动画会一直显示),说明并非用到的css在ios不兼容。可能的原因是,iOS设备上的特殊渲染优化可能会导致在Vue实例挂载之前,被Vue挂载的DOM元素内部的原有内容被移除或隐藏。 解决办法是把loading元素挪到最外层,与div#app同级,在vue实例初始化完成后利用mounted钩子函数移除loading元素。

最终方案:

1
2
3
4
5
6
7
8
9
<!-- public/index.html -->
<style></style>
<div id="loading-mask">
  <div class="loading-wrapper">
    <span class="loading-dot loading-dot-spin"><i></i><i></i><i></i><i></i></span>
    <div class="loading-text">正在加载</div>
  </div>
</div>
<div id="app"></div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// main.js
new Vue({
  router,
  store,
  mounted(){
    // 在Vue实例初始化完成后移除loading元素
    const loadingElement = document.querySelector('#loading-mask');
    document.body.removeChild(loadingElement);
    }
}).$mount("#app");
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy
© Licensed Under CC BY-NC-SA 4.0