我有一个Angular SPA,它从后端加载一堆数据并显示它们,比方说表。为了提供更好的用户体验,我在加载数据时隐藏这些表并显示一个微调器。所以我最终编写了这样的代码:
模板:
<div class="row">
<div class="col-md-12">
<spinner ng-show="ctrl.loading.unicorns"></spinner>
<ul ng-hide="ctrl.loading.unicorns">
<li ng-repeat="unicorn in ctrl.unicorns">{{ unicorn.name }}</li>
</ul>
</div>
</div>
控制器:
function unicornController() {
var ctrl = this;
ctrl.loading = {
unicorns: true
};
unicornService
.get()
.then(function(data) {
ctrl.unicorns = data;
})
.finally(function() {
ctrl.loading.unicorns = false;
});
return ctrl;
}
使用一个装载程序并不是什么大不了的事,但是当我在每个视图中都有3个装载程序时,感觉加载可以以更好的方式处理。我发现promises有一个$$state.status
属性,它确实保存了这个值,但是afaik我不应该使用它,因为它不是公共API的一部分。有没有其他方法可以实现这一点而不会弄乱本地标志?
答案 0 :(得分:1)
您可以找到自己做的方法,也可以找到现有方法。
以下是一个有用的项目,可以自动显示$http
个请求的进度。
安装(npm或bower)
$ npm install angular-loading-bar
$ bower install angular-loading-bar
包含
angular.module('myApp', ['angular-loading-bar'])
答案 1 :(得分:0)
如果您正在做很多事情并且需要独立加载器,那么为此实现特定的指令/组件是个好主意吗?
使用spinKit微调器的简单示例。
angular.module('app', []);
angular.module('app').component('loading', {
transclude: true,
template: `
<div class="spinner" ng-show="$ctrl.loading"></div>
<ng-transclude ng-hide="$ctrl.loading"></ng-transclud>
`,
bindings: {
promise: '<'
},
controller: function() {
this.loading = false;
this.$onChanges = function() {
if (this.promise != null) {
this.loading = true;
this.promise
.then(function() {
this.loading = false;
}.bind(this));
}
}.bind(this);
}
});
angular.module('app').controller('Example', function($timeout) {
this.emitPromise = function(propName) {
this[propName] = createRandomPromise()
.then(function(result) {
this[propName + 'Result'] = result;
}.bind(this));
}.bind(this);
function createRandomPromise() {
var time = Math.round(Math.random() * 3000); // up to 3s
return $timeout(function() {
return time;
}, time);
}
});
.spinner {
width: 40px;
height: 40px;
background-color: #333;
margin: 10px auto;
-webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
animation: sk-rotateplane 1.2s infinite ease-in-out;
}
@-webkit-keyframes sk-rotateplane {
0% {
-webkit-transform: perspective(120px)
}
50% {
-webkit-transform: perspective(120px) rotateY(180deg)
}
100% {
-webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg)
}
}
@keyframes sk-rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
}
50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
}
100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<div ng-app="app" ng-controller="Example as Ex">
<loading promise="Ex.x">
x result = {{Ex.xResult}}
</loading>
<br>
<button type="button" ng-click="Ex.emitPromise('x')">emit x</button>
<br>
<loading promise="Ex.y">
y result = {{Ex.yResult}}
</loading>
<br>
<button type="button" ng-click="Ex.emitPromise('y')">emit y</button>
</div>
或者,如果您希望可以使用指令将结果插入到转换范围:
angular.module('app', []);
angular.module('app').directive('loading', function($parse) {
return {
restrict: 'E',
transclude: true,
scope: true,
template: `
<div class="spinner" ng-show="loading"></div>
<div class="target" ng-hide="loading"></div>
`,
link: function($scope, $element, $attrs, $ctrl, $transclude) {
$scope.loading = false;
var targetElem = angular.element($element[0].querySelector('.target'));
$scope.$watch(watchFn, function(promise) {
if (promise != null) {
$scope.loading = true;
promise.then(function(result) {
$scope.loading = false;
$scope.result = result;
$transclude($scope, function (content) {
targetElem.empty();
targetElem.append(content);
});
});
}
});
function watchFn() {
return $parse($attrs.promise)($scope);
}
}
};
});
angular.module('app').controller('Example', function($timeout) {
this.parentValue = 'parent Value';
this.emitPromise = function(propName) {
this[propName] = createRandomPromise();
}.bind(this);
function createRandomPromise() {
var time = Math.round(Math.random() * 3000); // up to 3s
return $timeout(function() {
return time;
}, time);
}
});
.spinner {
width: 40px;
height: 40px;
background-color: #333;
margin: 10px auto;
-webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
animation: sk-rotateplane 1.2s infinite ease-in-out;
}
@-webkit-keyframes sk-rotateplane {
0% {
-webkit-transform: perspective(120px)
}
50% {
-webkit-transform: perspective(120px) rotateY(180deg)
}
100% {
-webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg)
}
}
@keyframes sk-rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
}
50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
}
100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<div ng-app="app" ng-controller="Example as Ex">
<loading promise="Ex.x">
x result = {{result}}
</loading>
<br>
<button type="button" ng-click="Ex.emitPromise('x')">emit x</button>
<br>
<loading promise="Ex.y">
y result = {{result}}<br>
Ex.parentValue = {{Ex.parentValue}}
</loading>
<br>
<button type="button" ng-click="Ex.emitPromise('y')">emit y</button>
</div>