• 实现页面加载等待动画很简单吗?


    在手机上打开页面时,经常会因为网络不好导致需要较长的加载时间,如果这段时间内只是显示一个“白板”,用户体验非常不好。通常的解决方案就是完整打开页面前给用户展示一个加载动画,让用户能够看到页面还活着呢。本以为是个很简单的活,真做起来才发现【有不少学问】!

    一、首先要搞清楚的问题是,为什么加载过程中会出现”白板“,下面用Chrome开发者工具的Timeline分析面板做了几个实验。

    1、不加载资源文件
    图片描述
    顺序:加载、解析、渲染、绘制

    2、加载CSS
    图片描述
    加载外部的CSS文件会阻止渲染,不论link的标签放在什么位置上。
    顺序:加载、解析、加载(阻塞了渲染)、渲染、绘制

    3、加载JS
    a、在body前加载外部的JS文件会阻止渲染
    图片描述
    顺序:加载、解析、渲染(?)、加载(阻塞)、解析(JS执行完多了个解析)、渲染、绘制

    b、在body后加载外部的JS文件不会阻止渲染
    图片描述
    顺序:加载、解析、渲染、绘制、加载、解析、渲染、绘制

    4、在<script>标签中动态创建link标签加载CSS
    图片描述
    加载CSS中断了页面的渲染和绘制

    5、在<script>标签中通过setTimeout函数动态创建link标签加载CSS
    图片描述
    加载CSS没有中断。我理解这是因为JS是单线程的,放在timeout里创建的link去排队,浏览器就先不管它了。

    二、基于上面的测试,实现页面加载动画理想的方式是什么?

    先定好目标:尽快让用户看到变化,不要让用户以为页面已经不响应,再逐步加载内容。
    最快的方式就是做一个空的页面,不加载任何外部资源(包括:CSS和JS)。页面上方加载动画的CSS定义和页面元素,提供异步加载页面元素、CSS和JS文件的JS。通过JS加载各类资源成功后关闭动画效果,清除不必要的内容。

    这样就来个新问题,如何实现动态加载问题?

    外部文件的动态加载问题很多文章都深入分析过了,简单说,就是用异步加载,但是要考虑到各个JS文件的依赖关系问题。综合比较了一下,决定requirejs实现动态加载。因为最近一直用angular,所以下面的代码是require.js+angular。

    HTML

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <meta content="width=device-width,user-scalable=no,initial-scale=1.0" name="viewport">
            <base href='/'>
            <title>loading</title>
            <style id='loadingStyle' type="text/css">
                /*省略了,这里是loading元素转圈的样式,为了快应该压缩了再放里面*/
            </style>
        </head>
        <body>
            <div id="content" ng-app="app" ng-controller="ctrl">
                <ul class='list-group'>
                    <li class='list-group-item' ng-repeat="d in data"><i ng-bind="d"></i></li>
                </ul>
            </div>
            <div class="loading"><div class='loading-indicator'><i></i></div></div>
            <script src="static/js/require.js" defer async data-main="test/loading/loader.js?_=11"></script>
        </body>
    </html>

    loader.js
    因为angular不是AMD,所以用shim引用成angular全局变量

    require.config({
        paths: {
            "angular": "/static/js/angular.min",
        },
        shim: {
            "angular": {
                exports: "angular"
            },
        },
        deps: ['/test/loading/app.js?_=10']
    });

    app.js
    如果真的要动态添加样式,建议先获得数据,把数据展现出来,在加载样式,这样就能让用户今早看到变化。

    define(["angular"], function(angular) {
        'use strict';
        angular.module('app', []).controller('ctrl', ['$scope', '$timeout', function($scope, $timeout) {
            $scope.data = [];
            // 模拟长时间获得数据
            $timeout(function() {
                for (var i = 0; i < 100; i++) {
                    $scope.data.push('data:' + i);
                }
                // 模拟长时间获得样式
                $timeout(function() {
                    var link, head;
                    link = document.createElement('link');
                    link.href = "/test/loading/app.css?_=" + (new Date()).getTime();
                    link.rel = 'stylesheet';
                    link.onload = function() {
                        var eleLoading, eleStyle;
                        eleLoading = document.querySelector('.loading');
                        eleLoading.parentNode.removeChild(eleLoading);
                        eleStyle = document.querySelector('#loadingStyle');
                        eleStyle.parentNode.removeChild(eleStyle);
                    };
                    head = document.querySelector('head');
                    head.appendChild(link);
                }, 2000);
            }, 2000);
        }]);
    });

    app.css

    #content{color:red;}

    三、还可以做什么?

    可以考虑页面的布局也动态加载,这样用户可以先看见页面的框架,然后再获取数据填到框架中。但是还没有想到成熟的解决方案。

  • 相关阅读:
    CCF NOI1062 计算曼哈顿距离
    CCF NOI1061 Wifi密码
    CCF NOI1073 放苹果
    CCF NOI1072 爬楼梯
    CCF NOI1071 Pell数列
    CCF NOI1064 计算斐波那契第n项
    NOI训练行动路线图
    CCF NOI1060 雷同检测
    CCF NOI1059 表达式求值
    CCF NOI1057 石头剪刀布
  • 原文地址:https://www.cnblogs.com/10manongit/p/12656045.html
Copyright © 2020-2023  润新知