Angularjs:如何在使用'解决'在$routeProvider中

Angularjs: How to display loading-icon when using 'resolve' in $routeProvider?

本文关键字:解决 routeProvider Angularjs      更新时间:2023-09-26

以下代码通过服务读取,并在网页上显示特定"页面类别"(字符串)的"页面"对象列表。使用$routeProvider.when()中的解析对象属性,我可以推迟更新视图,直到新值准备好为止。

两个问题:

  1. 当要求一个新的页面列表时,我想显示一个加载图标。当从服务器开始读取(并且应该显示加载图标)时,我如何(以非黑客的方式)检测事件?我想我可以在服务中做一些类似$('.pages loading icon').show()的事情,但发现它太依赖gui了,太放在服务中了。

  2. 当新值准备好时,我希望旧值淡出,新值淡出。什么是"棱角分明"的方法?我曾尝试使用$watch在控制器中执行此操作,但这会导致在淡出开始前不久显示新值。

代码:

app.js:

$routeProvider.when('/:cat', { templateUrl: 'partials/view.html', controller: RouteCtrl, resolve: RouteCtrl.resolve});

controllers.js:

function RouteCtrl($scope, $routeParams, pages) {
        $scope.params = $routeParams;
        $scope.pages = pages;
    }
RouteCtrl.resolve={
    pages: function($routeParams, Pages){
        if($routeParams.hasOwnProperty('cat')){
            return Pages.query($routeParams.cat);
        }
    }
}

services.js:最后读取的页面存储在currentPages中,其类别存储在lastCat中。

factory('Pages', function($resource, $q, $timeout){
    return {
        res: $resource('jsonService/cat=:cat', {}, {
            query: {method:'GET', params:{cat:'cat'}, isArray:true}
        }),
        lastCat: null,
        currentPages: null,
        query: function(cat) {
            var res = this.res;
            if(cat != this.lastCat){
                var deferred = $q.defer();
                var p = res.query({'cat':cat}, function(){
                    deferred.resolve(p);
                });
                this.lastCat = cat;
                this.currentPages = deferred.promise;
            }
            return this.currentPages;
        }
    };
})

view.html

<ul >
    <li ng-repeat="page in pages">
        <a href="#{{params.cat}}/{{page.slug}}">{{page.title}}</a>
    </li>
</ul>

不确定这是否会在您的代码中工作,因为您有$resource集成。但研究角度事件可能是值得的:$routeChangeStart$routeChangeSuccess

在html:中

<span ng-show="isViewLoading"> loading the view... </span>

在控制器中(定义了上面html的范围):

$scope.isViewLoading = false;
$scope.$on('$routeChangeStart', function() {
  $scope.isViewLoading = true;
});
$scope.$on('$routeChangeSuccess', function() {
  $scope.isViewLoading = false;
});
$scope.$on('$routeChangeError', function() {
  $scope.isViewLoading = false;
});

angular的路由系统似乎有点有限。。

这为我解决了问题:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm

此外,关于触发两次的事件:如果您设置了一条路线,则映射到"a/b/c"角度会自动设置另一条路线、"a/b/c/"(带尾部斜线)重定向到第一条路线(反之亦然),并同时触发两次事件。我只是测试是否存在路由参数。

关于路由系统的有限条件:有这种来自角度的拉力,以扩展其能力。

您将希望使用$rootScope,因为监视控制器的$scope仅限于该控制器,而且您正在从一个视图(一个控制器)切换到另一个视图。因此,让一个代码适合所有代码是有意义的。

$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams){ ... })

在该功能中,设置$rootScope.isLoadingState,它将显示您的装载指示器。

然后使用

$rootScope.$on('$stateChangeSuccess', 
function(event, toState, toParams, fromState, fromParams){ ... })

取消设置该变量。

此处完整参考

您还可以使用ng-show指令。只需检查您的模型是否为空,并显示如下DOM子集:

    <!-- model not ready -->
    <div style="width: 200" ng-show="lines == ''">
      <div class="progress progress-striped active">
         <div class="bar" style="width: 0%;"></div>
      </div>
    </div>
    <!-- your model code -->
    <ul class="nav nav-tabs nav-stacked">
      <li ng-repeat="line in lines">
        {{line.Id}}
      </li>
    </ul>

我喜欢'ng-show'。。。但是Angular UI项目的'ui-if'更好。。由于从DOM中删除HTML代码。。。

<span ui-if = "isViewLoading"> loading the view... </span>

_e

您可以创建一个指令,该指令将根据您在服务调用前后发送的广播显示,您可以将其放在$rootScope上。因此,如果您正在调用一个工厂来处理发出的通用POST/GET调用,那么就在调用之前,您可以在$rootScope上调用一个函数,例如"$rootScope.startLoading()",当它完成调用"$rootScope.doeLoading())"时,这些方法中的每一个都会广播一个事件,供您根据指令进行操作。然后,您只需处理捕获事件的指令"scope.$on("startLoading",func(

这样你就可以有一个很好的通用加载覆盖。