如何在 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 处有很多模块可以处理加载动画。例如,这些:
- https://github.com/cgross/angular-busy
- https://github.com/chieffancypants/angular-loading-bar(我在我的应用程序中使用了这个)
- https://github.com/McNull/angular-block-ui 等
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>
您可以尝试这样的事情(最简单的解决方案):
设置加载器animation/picture:<div class="loader" ng-show="isLoading"></div>
在div
元素上添加点击事件:
- 然后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>
我在网页上使用<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 处有很多模块可以处理加载动画。例如,这些:
- https://github.com/cgross/angular-busy
- https://github.com/chieffancypants/angular-loading-bar(我在我的应用程序中使用了这个)
- https://github.com/McNull/angular-block-ui 等
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>
您可以尝试这样的事情(最简单的解决方案):
设置加载器animation/picture:
<div class="loader" ng-show="isLoading"></div>
在
div
元素上添加点击事件:- 然后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>