【问题标题】:How to do preloader for `ng-view` in Angular JS?如何在Angular JS中为`ng-view`做预加载器?
【发布时间】:2015-07-18 09:40:49
【问题描述】:

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

现在的问题是,单击后我得到带有空表单的 HTML 模板,但 AJAX 请求仍在工作。几秒钟后,表单 HTML 是来自 AJAX 的归档数据。

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

【问题讨论】:

  • “预加载器”是什么意思? ng-cloak 指令可以解决您的问题吗?
  • 我的意思是,向用户显示内容正在加载,并且在ng-view中不显示 HTML
  • ng-cloakng-view如何配合使用?
  • 我现在不明白ng-cloak 不是你想要的。它隐藏内容直到应用程序被引导。

标签: angularjs ng-view


【解决方案1】:

从 PACE Loader 下载 javascript 和 css 文件。 使用 ng-views 玩起节奏加载器。希望这对尝试将 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>

【讨论】:

    【解决方案2】:

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

    另外,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>
    

    【讨论】:

    • 你没有完全理解我。我可以使用您的解决方案,但我需要 ng-view 的预加载器,例如:&lt;div ng-view data-loading&gt;&lt;/div&gt;
    • @Hamed,我已经为您编写了一个基于 angular-loading-bar 的示例。这并不理想,但我希望它会有所帮助。
    • @Hamed,你解决问题了吗?可以分享一下解决方法吗?
    【解决方案3】:

    你可以试试这样的(最简单的解决方案):

    1. 设置你的加载器动画/图片:&lt;div class="loader" ng-show="isLoading"&gt;&lt;/div&gt;

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 2014-09-13
      • 2015-11-25
      • 2015-02-19
      相关资源
      最近更新 更多