将AngularJS路由更改延迟,直到模型加载完成,以防止闪烁。
将AngularJS路由更改延迟,直到模型加载完成,以防止闪烁。
我在想是否有一种类似于Gmail的方式,使得AngularJS可以延迟显示新路由直到每个模型及其数据已被其各自的服务获取。
例如,如果有一个来列出所有的Project,并有模板来显示这些Project,则<project.query()>会在显示新页面之前完全获取。
在此之前,旧页面仍将继续显示(例如,如果我正在浏览其他页面,然后决定查看这个Project索引页)。
admin 更改状态以发布 2023年5月24日
这里有一个适用于Angular 1.0.2的最小工作示例:
模板:
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()已经返回一个promise(也称之为deferred),所以我们实际上不需要自己创建。因此,我们可以简化MyCtrl.resolve如下:
MyCtrl.resolve = { datasets : function($http) { return $http({ method: 'GET', url: 'http://fiddle.jshell.net/' }); } };
$http()的结果包含数据,状态,头和配置对象,因此我们需要将MyCtrl的内容更改为:
$scope.datasets = datasets.data;
$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; } }
请注意,控制器定义包含一个解析对象,声明应该在控制器构造函数中可用的东西。在这里,phones
被注入到控制器中,它在resolve
属性中定义。
resolve.phones
函数负责返回一个承诺。所有承诺都被收集起来,路由更改被延迟直到所有承诺都被解决。
工作演示:http://mhevery.github.com/angular-phonecat/app/#/phones
来源:https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831