将AngularJS路由更改延迟,直到模型加载完成,以防止闪烁。

9 浏览
0 Comments

将AngularJS路由更改延迟,直到模型加载完成,以防止闪烁。

我在想是否有一种类似于Gmail的方式,使得AngularJS可以延迟显示新路由直到每个模型及其数据已被其各自的服务获取

例如,如果有一个来列出所有的Project,并有模板来显示这些Project,则<project.query()>会在显示新页面之前完全获取。

在此之前,旧页面仍将继续显示(例如,如果我正在浏览其他页面,然后决定查看这个Project索引页)。

admin 更改状态以发布 2023年5月24日
0
0 Comments

这里有一个适用于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://jsfiddle.net/dTJ9N/3/

简化版:

由于$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;

http://jsfiddle.net/dTJ9N/5/

0
0 Comments

$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

0