如何在 Angular JS 中为 `ng-view` 做预加载?

How to do preloader for `ng-view` in Angular JS?

我在网页上使用<div ng-view></div>。 当我在块 <div> 中单击 link 时,加载 HTML 模板已在 routeProvider 中设置。还一起完成请求 AJAX returns 已加载模板的数据。

现在的问题是,点击后我得到了 HTML 空表单模板,但仍在处理 AJAX 请求。几秒钟后,表格 HTML 是来自 AJAX.

的文件数据

如何预加载目录 ng-view 的页面?

这里好像有一些类似的问题:

  • Angularjs loading screen on ajax request
  • Angular JS loading screen and page animation.

此外,在 http://ngmodules.org 处有很多模块可以处理加载动画。例如,这些:

UPD: 我已经根据 angular-loading-bar 的工作原理编写了一个简单的解决方案。我没有用 ng-view 测试它,但它可以与 ui-view 一起使用。不是最终的解决方案,需要打磨

angular.module('ui')

.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('LoadingListener');
}])

.factory('LoadingListener', [ '$q', '$rootScope', function($q, $rootScope) {
    var reqsActive = 0;

    function onResponse() {
        reqsActive--;
        if (reqsActive === 0) {
            $rootScope.$broadcast('loading:completed');
        }
    }

    return {
        'request': function(config) {
            if (reqsActive === 0) {
                $rootScope.$broadcast('loading:started');
            }
            reqsActive++;
            return config;
        },
        'response': function(response) {
            if (!response || !response.config) {
                return response;
            }
            onResponse();
            return response;
        },
        'responseError': function(rejection) {
            if (!rejection || !rejection.config) {
                return $q.reject(rejection);
            }
            onResponse();
            return $q.reject(rejection);
        },
        isLoadingActive : function() {
            return reqsActive === 0;
        }
    };
}])

.directive('loadingListener', [ '$rootScope', 'LoadingListener', function($rootScope, LoadingListener) {

    var tpl = '<div class="loading-indicator" style="position: absolute; height: 100%; width: 100%; background-color: #fff; z-index: 1000">Loading...</div>';

    return {
        restrict: 'CA',
        link: function linkFn(scope, elem, attr) {
            var indicator = angular.element(tpl);
            elem.prepend(indicator);

            elem.css('position', 'relative');
            if (!LoadingListener.isLoadingActive()) {
                indicator.css('display', 'none');
            }

            $rootScope.$on('loading:started', function () {
                indicator.css('display', 'block');
            });
            $rootScope.$on('loading:completed', function () {
                indicator.css('display', 'none');
            });
        }
    };
}]);

可以这样使用:

<section class="content ui-view" loading-listener></section>

您可以尝试这样的事情(最简单的解决方案):

  1. 设置加载器animation/picture:<div class="loader" ng-show="isLoading"></div>

  2. div元素上添加点击事件:

  3. 然后AJAX请求成功设置isLoading=true

从 PACE Loader 下载 javascript 和 css 文件。 使用 ng-views 玩弄 pace loader。希望这对尝试将 PACE.JS 与 Angular 一起使用的人有所帮助。在此示例中,我使用 ng-router 在视图之间导航。

app.js

var animateApp = angular.module('route-change-loader', ['ngRoute']);

var slowResolve = function(slowDataService){
    return slowDataService.getContacts();
  };
  slowResolve.$inject = ['slowDataService'];

// ROUTING ===============================================
// set our routing for this application
  // each route will pull in a different controller
  animateApp.config(function($routeProvider) {

    $routeProvider

    // home page
    .when('/route1', {
      templateUrl: 'route1.html',
      controller: 'slowCtrl',
      controllerAs:'ctrl',
      resolve: {
        contacts:slowResolve
      }
    })
    .otherwise({
      templateUrl:'default.html'
    });
  });


var SlowCtrl = function(contacts) {
  this.contacts = contacts;
};
  SlowCtrl.$inject = ['contacts'];

  angular.extend(SlowCtrl.prototype, {
    message:'Look Mom, No Lag!',
    contacts: []
  });

animateApp.controller('slowCtrl', SlowCtrl);


  var SlowDataService = function($timeout){
      this.$timeout = $timeout;
    };
    SlowDataService.$inject = ['$timeout'];

    angular.extend(SlowDataService.prototype, {
      contacts:[{
        name:'Todd Moto',
        blog:'http://toddmotto.com/',
        twitter:'@toddmotto'
      },{
        name:'Jeremy Likness',
        blog:'http://csharperimage.jeremylikness.com/',
        twitter:'@jeremylikness'
      },{
        name:'John Papa',
        blog:'http://www.johnpapa.net/',
        twitter:'@John_Papa'
      },{
        name:'Josh Carroll',
        blog:'http://www.technofattie.com/',
        twitter:'@jwcarroll'
      }],
      getContacts:function(){
        var _this = this;
        return this.$timeout(function(){
          return angular.copy(_this.contacts);
        }, 1000);
      }
    });

animateApp.service('slowDataService', SlowDataService);

index.html

<!DOCTYPE html>
<html lang="en-us">
<head>
  <meta charset="utf-8">
  <title>Test Example</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
  <link rel="stylesheet" href="pace.css">
  <script src="http://code.angularjs.org/1.2.13/angular.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular-route.js"></script>
  <script src="app.js"></script>
  <script src="pace.js"></script>

</head>
<body ng-app="route-change-loader">
  <div class="container">
    <div class="masthead">
      <ul class="nav nav-tabs">
        <li>
          <a href="#/default">Default</a>
        </li>
        <li>
          <a href="#/route1">Slow Loading Controller</a>
        </li>
      </ul>
    </div>
    <!-- Jumbotron -->
    <div class="row">
      <route-loading-indicator></route-loading-indicator>
      <div ng-if="!isRouteLoading" class="col-lg-12" ng-view=""></div>
    </div>
    <!-- Site footer -->
    <div class="footer">
      <p>by <b>Ritesh Karwa</b> </a>
      </p>
    </div>
  </div>
</body>

</html>

default.html

<h1>Click on the tabs to change routes</h1>

route1.html

<h1>{{ctrl.message}}</h1>
<table class="table table-striped">
  <thead>
    <tr>
      <th>Name</th>
      <th>Blog</th>
      <th>Twitter</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat='contact in ctrl.contacts'>
      <td>{{contact.name}}</td>
      <td>{{contact.blog}}</td>
      <td>{{contact.twitter}}</td>
    </tr>
  </tbody>
</table>