在根级别显示加载指示器,直到所有路由解析完成
Show loading indicator at root level until all route resolves are complete
我已经在谷歌上搜索过这个问题,但找不到有效的解决方案。
我正在使用 AngularJS 1.5.5 和 .NET Web API 2 构建 Web 应用程序,我只想隐藏 ng-view
元素直到所有路线上的决议已完成。
我正在尝试使用 $routeChangeStart
和 $routeChangeSuccess
在索引 html 中使用的 $rootScope
上设置一个变量来显示加载指示器并隐藏内容,直到变量为 false
.
这是我的 routeChange 属性的路由代码:
_app.config([
'$routeProvider', '$httpProvider', '$provide',
function ($routeProvider, $httpProvider, $provide) {
$routeProvider.when('/Account',
{
templateUrl: '/Content/js/areas/account/account.html',
controller: 'accountController',
resolve: {
$accountResolver: function (accountService) {
return accountService.getMyAccountData();
}
},
caseInsensitiveMatch: true
});
$routeProvider.otherwise({ redirectTo: '404' });
}
]);
_app.run(['$rootScope', '$location', '$window', '$q', 'authService',
function ($rootScope, $location, $window, $q, authService) {
$rootScope.$on("$routeChangeStart",
function (e, curr, prev) {
$rootScope.$loadingRoute = true;
});
$rootScope.$on("$routeChangeSuccess",
function (evt, next) {
$rootScope.$loadingRoute = false;
});
$rootScope.$on("$routeChangeError",
function (evt, next) {
$rootScope.$loadingRoute = false;
});
}]);
这是我的 html 使用 $loadingRoute
变量:
<body class="ng-cloak" data-ng-app="wishlist" data-ng-controller="appController">
<wl-header></wl-header>
<preloader ng-if="$loadingRoute"></preloader>
<section ng-view ng-if="!$loadingRoute" class="container ng-cloak"></section>
</body>
我知道有很多文章对此进行了介绍,但 none 似乎对我有用。正如预期的那样,当路由更改开始时,$loadingRoute
被设置为 true,如果我将 {{$loadingRoute}}
添加到 <section></section>
标记之前的 HTML,我将看到这一点。然而,在解决 $accountResolver
之前,$routeChangeSuccess
被解雇,设置 $rootScope.$loadingRoute = false
这是意外的。
我的印象是 $routeChangeSuccess
只有在当前路线上的所有解析都完成后才会被解雇。
我在这里做错了什么吗?还是 Angular 只是改变了?
编辑:我还想补充一点,这种方法在以前的项目中有效,所以我真的不知道出了什么问题。我可以在每个页面控制器中手动设置$rootScope.$loadingRoute
,但感觉太脏且无法维护。
编辑 2:
_app.factory('accountService', [
'accountResource',
function (accountResource) {
var _self = this;
return {
register: function (authData) {
return accountResource.register(authData);
},
getMyAccountData: function () {
return accountResource.getMyAccountData();
}
}
}
]);
_app.factory('accountResource', [
'$resource', 'rootUrl',
function ($resource, rootUrl) {
var api = rootUrl() + 'api/Account';
return $resource(api,
{},
{
register: {
method: 'POST',
url: '{0}/register'.format(api)
},
getMyAccountData: {
method: 'GET',
url: '{0}/GetMyAccountData'.format(api)
}
});
}
])
为了让解析器延迟路由更改,它应该 return 一个承诺。否则路由更改会立即发生,这就是在 accountService.getMyAccountData()
的承诺得到解决之前触发 $routeChangeSuccess
时发生的情况。
问题是 $resource
方法(因此 accountService.getMyAccountData()
)return 异步填充数据的自填充对象。此数据的承诺可用作 $promise
属性(请参阅 the reference),因此它应该用于解析器:
$accountResolver: function (accountService) {
return accountService.getMyAccountData().$promise;
}
如果 accountService
应该是 accountResource
的纯粹基于 promise 的包装器,一种更简洁的方法是 return 来自其方法的 promise:
getMyAccountData: function () {
return accountResource.getMyAccountData().$promise;
}
我已经在谷歌上搜索过这个问题,但找不到有效的解决方案。
我正在使用 AngularJS 1.5.5 和 .NET Web API 2 构建 Web 应用程序,我只想隐藏 ng-view
元素直到所有路线上的决议已完成。
我正在尝试使用 $routeChangeStart
和 $routeChangeSuccess
在索引 html 中使用的 $rootScope
上设置一个变量来显示加载指示器并隐藏内容,直到变量为 false
.
这是我的 routeChange 属性的路由代码:
_app.config([
'$routeProvider', '$httpProvider', '$provide',
function ($routeProvider, $httpProvider, $provide) {
$routeProvider.when('/Account',
{
templateUrl: '/Content/js/areas/account/account.html',
controller: 'accountController',
resolve: {
$accountResolver: function (accountService) {
return accountService.getMyAccountData();
}
},
caseInsensitiveMatch: true
});
$routeProvider.otherwise({ redirectTo: '404' });
}
]);
_app.run(['$rootScope', '$location', '$window', '$q', 'authService',
function ($rootScope, $location, $window, $q, authService) {
$rootScope.$on("$routeChangeStart",
function (e, curr, prev) {
$rootScope.$loadingRoute = true;
});
$rootScope.$on("$routeChangeSuccess",
function (evt, next) {
$rootScope.$loadingRoute = false;
});
$rootScope.$on("$routeChangeError",
function (evt, next) {
$rootScope.$loadingRoute = false;
});
}]);
这是我的 html 使用 $loadingRoute
变量:
<body class="ng-cloak" data-ng-app="wishlist" data-ng-controller="appController">
<wl-header></wl-header>
<preloader ng-if="$loadingRoute"></preloader>
<section ng-view ng-if="!$loadingRoute" class="container ng-cloak"></section>
</body>
我知道有很多文章对此进行了介绍,但 none 似乎对我有用。正如预期的那样,当路由更改开始时,$loadingRoute
被设置为 true,如果我将 {{$loadingRoute}}
添加到 <section></section>
标记之前的 HTML,我将看到这一点。然而,在解决 $accountResolver
之前,$routeChangeSuccess
被解雇,设置 $rootScope.$loadingRoute = false
这是意外的。
我的印象是 $routeChangeSuccess
只有在当前路线上的所有解析都完成后才会被解雇。
我在这里做错了什么吗?还是 Angular 只是改变了?
编辑:我还想补充一点,这种方法在以前的项目中有效,所以我真的不知道出了什么问题。我可以在每个页面控制器中手动设置$rootScope.$loadingRoute
,但感觉太脏且无法维护。
编辑 2:
_app.factory('accountService', [
'accountResource',
function (accountResource) {
var _self = this;
return {
register: function (authData) {
return accountResource.register(authData);
},
getMyAccountData: function () {
return accountResource.getMyAccountData();
}
}
}
]);
_app.factory('accountResource', [
'$resource', 'rootUrl',
function ($resource, rootUrl) {
var api = rootUrl() + 'api/Account';
return $resource(api,
{},
{
register: {
method: 'POST',
url: '{0}/register'.format(api)
},
getMyAccountData: {
method: 'GET',
url: '{0}/GetMyAccountData'.format(api)
}
});
}
])
为了让解析器延迟路由更改,它应该 return 一个承诺。否则路由更改会立即发生,这就是在 accountService.getMyAccountData()
的承诺得到解决之前触发 $routeChangeSuccess
时发生的情况。
问题是 $resource
方法(因此 accountService.getMyAccountData()
)return 异步填充数据的自填充对象。此数据的承诺可用作 $promise
属性(请参阅 the reference),因此它应该用于解析器:
$accountResolver: function (accountService) {
return accountService.getMyAccountData().$promise;
}
如果 accountService
应该是 accountResource
的纯粹基于 promise 的包装器,一种更简洁的方法是 return 来自其方法的 promise:
getMyAccountData: function () {
return accountResource.getMyAccountData().$promise;
}