延迟 AngularJS 路由更改,直到加载模型以防止闪烁
我想知道AngularJS是否有一种方法(类似于Gmail)延迟显示新路线,直到每个模型及其数据都使用其各自的服务获取之后。
例如,如果有 一个列出了所有项目的模板,并且它是显示这些项目的模板,则在显示新页面之前将完全获取。ProjectsController
project_index.html
Project.query()
在此之前,旧页面仍将继续显示(例如,如果我正在浏览另一个页面,然后决定查看此项目索引)。
我想知道AngularJS是否有一种方法(类似于Gmail)延迟显示新路线,直到每个模型及其数据都使用其各自的服务获取之后。
例如,如果有 一个列出了所有项目的模板,并且它是显示这些项目的模板,则在显示新页面之前将完全获取。ProjectsController
project_index.html
Project.query()
在此之前,旧页面仍将继续显示(例如,如果我正在浏览另一个页面,然后决定查看此项目索引)。
$routeProvider resolve 属性允许在加载数据之前延迟路由更改。
首先定义一个具有类似如下属性的路由。resolve
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: PhoneListCtrl,
resolve: PhoneListCtrl.resolve}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: PhoneDetailCtrl,
resolve: PhoneDetailCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
请注意,该属性是在路由上定义的。resolve
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone, $q) {
// see: https://groups.google.com/forum/?fromgroups=#!topic/angular/DGf7yyD4Oc4
var deferred = $q.defer();
Phone.query(function(successData) {
deferred.resolve(successData);
}, function(errorData) {
deferred.reject(); // you could optionally pass error data here
});
return deferred.promise;
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
请注意,控制器定义包含一个 resolve 对象,该对象声明控制器构造函数应可以使用的内容。这里,它被注入到控制器中,并在属性中定义。phones
resolve
该函数负责返回承诺。收集所有承诺,并延迟路由更改,直到所有承诺都得到解决。resolve.phones
工作演示:http://mhevery.github.com/angular-phonecat/app/#/phones 来源:https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831
下面是一个适用于 Angular 1.0.2 的最小工作示例
模板:
<script type="text/ng-template" id="/editor-tpl.html">
Editor Template {{datasets}}
</script>
<div ng-view>
</div>
JavaScript:
function MyCtrl($scope, datasets) {
$scope.datasets = datasets;
}
MyCtrl.resolve = {
datasets : function($q, $http) {
var deferred = $q.defer();
$http({method: 'GET', url: '/someUrl'})
.success(function(data) {
deferred.resolve(data)
})
.error(function(data){
//actually you'd want deffered.reject(data) here
//but to show what would happen on success..
deferred.resolve("error value");
});
return deferred.promise;
}
};
var myApp = angular.module('myApp', [], function($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/editor-tpl.html',
controller: MyCtrl,
resolve: MyCtrl.resolve
});
});
精简版:
由于$http()已经返回了一个承诺(又名延迟),我们实际上不需要创建自己的承诺。因此,我们可以简化MyCtrl。解析为:
MyCtrl.resolve = {
datasets : function($http) {
return $http({
method: 'GET',
url: 'http://fiddle.jshell.net/'
});
}
};
$http() 的结果包含数据、状态、标头和配置对象,因此我们需要将 MyCtrl 的主体更改为:
$scope.datasets = datasets.data;