在ui-router解析期间应用加载微调器

Mik*_*378 35 web-applications angularjs single-page-application angular-ui-router

resolve$routeProvider允许在呈现相应视图之前执行某些作业的属性.

如果我想在执行这些作业时显示微调器以增加用户体验,该怎么办?
实际上,否则用户会感觉应用程序已被阻止,因为例如没有显示视图元素一些毫秒> 600.

当然,有一种方法可以定义当前视图中的全局div元素,以便通过该函数显示微调器.但我不想隐藏整个页面,中间只有一个可怜的微调器. 我希望我的webapp的某些页面在加载显示方式上有所不同.$scope.$rootChangeStart

我遇到了这个有趣的帖子,其中包含我上面描述的确切问题:

这种方法导致可怕的UI体验.用户单击按钮刷新列表或其他内容,整个屏幕在通用微调器中被覆盖,因为库无法仅为实际受状态更改影响的视图显示微调器.不用了,谢谢.

在任何情况下,在我提交此问题后,我意识到"解析"功能是一种反模式.它等待所有承诺解决然后动态状态变化.这是完全错误的 - 您希望状态之间的转换动画与数据加载并行运行,以便前者可以覆盖后者.

例如,假设您有一个项目列表,单击其中一个项目会隐藏列表并在不同视图中显示项目的详细信息.如果我们对项目详细信息的异步​​加载平均需要400毫秒,那么在大多数情况下我们可以通过在列表视图上放置300毫秒"离开"动画和300毫秒"输入"动画来几乎完全掩盖负载在项目详细信息视图上.这样我们就可以为UI提供更加流畅的感觉,并且在大多数情况下可以避免显示微调器.

但是,这要求我们在同一时刻启动异步加载和状态更改动画.如果我们使用"resolve",那么整个异步动画就会在动画开始之前发生.用户单击,查看微调器,然后查看过渡动画.整个状态的变化需要大约1000毫秒,这太慢了.

"Resolve"可以是缓存不同视图之间依赖关系的有用方法,如果它可以选择不等待promises,但是在状态更改开始之前始终解析它们的当前行为使得它几乎无用,IMO.对于涉及异步加载的任何依赖项,应该避免使用它.

我真的应该停止使用resolve加载一些数据而不是直接在相应的控制器中加载它们吗?这样我就可以在作业执行时以及在视图中我想要的位置更新相应的视图,而不是全局.

tas*_*ATT 51

您可以使用侦听的指令,$routeChangeStart例如在触发时显示该元素:

app.directive('showDuringResolve', function($rootScope) {

  return {
    link: function(scope, element) {

      element.addClass('ng-hide');

      var unregister = $rootScope.$on('$routeChangeStart', function() {
        element.removeClass('ng-hide');
      });

      scope.$on('$destroy', unregister);
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

然后将它放在特定视图的加载器上,例如:

查看1:

<div show-during-resolve class="alert alert-info">
  <strong>Loading.</strong>
  Please hold.
</div>
Run Code Online (Sandbox Code Playgroud)

观点2:

<span show-during-resolve class="glyphicon glyphicon-refresh"></span>
Run Code Online (Sandbox Code Playgroud)

此解决方案(以及许多其他解决方案)的问题在于,如果您从外部站点浏览到其中一个路径,则不会加载先前的ng-view模板,因此在解析期间您的页面可能只是空白.

这可以通过创建一个充当回退加载器的指令来解决.$routeChangeStart只有在没有以前的路线时,它才会监听并显示装载机.

一个基本的例子:

app.directive('resolveLoader', function($rootScope, $timeout) {

  return {
    restrict: 'E',
    replace: true,
    template: '<div class="alert alert-success ng-hide"><strong>Welcome!</strong> Content is loading, please hold.</div>',
    link: function(scope, element) {

      $rootScope.$on('$routeChangeStart', function(event, currentRoute, previousRoute) {
        if (previousRoute) return;

        $timeout(function() {
          element.removeClass('ng-hide');
        });
      });

      $rootScope.$on('$routeChangeSuccess', function() {
        element.addClass('ng-hide');
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

使用ng-view将后备加载器放置在元素外部:

<body>
  <resolve-loader></resolve-loader>
  <div ng-view class="fadein"></div>
</body>
Run Code Online (Sandbox Code Playgroud)

演示全部: http ://plnkr.co/edit/7clxvUtuDBKfNmUJdbL3?p = preview

  • 这是链接功能的计时问题.如果使用templateUrl,这应该就是您所需要的:http://plnkr.co/edit/31qu9xcZCCEzSfHn5YyN?p = preview我稍后会在有时间并更新答案时仔细查看. (4认同)
  • 更新版本的ui-router从`$ routeChangeStart`更新为`$ stateChangeStart` https://github.com/angular-ui/ui-router/wiki#state-change-events (3认同)

Pra*_*tta 29

我觉得这很整洁

app.run(['$rootScope', '$state',function($rootScope, $state){

  $rootScope.$on('$stateChangeStart',function(){
      $rootScope.stateIsLoading = true;
 });


  $rootScope.$on('$stateChangeSuccess',function(){
      $rootScope.stateIsLoading = false;
 });

}]);
Run Code Online (Sandbox Code Playgroud)

然后在视图上

<div ng-show='stateIsLoading'>
  <strong>Loading.</strong>
</div>
Run Code Online (Sandbox Code Playgroud)


sid*_*son 11

为了进一步了解Pranay的答案,我就是这样做的.

JS:

app.run(['$rootScope',function($rootScope){

    $rootScope.stateIsLoading = false;
    $rootScope.$on('$routeChangeStart', function() {
        $rootScope.stateIsLoading = true;
    });
    $rootScope.$on('$routeChangeSuccess', function() {
        $rootScope.stateIsLoading = false;
    });
    $rootScope.$on('$routeChangeError', function() {
        //catch error
    });

}]);
Run Code Online (Sandbox Code Playgroud)

HTML

<section ng-if="!stateIsLoading" ng-view></section>
<section ng-if="stateIsLoading">Loading...</section>
Run Code Online (Sandbox Code Playgroud)

  • 在UI路由器的新版本中,它是$ stateChangeStart和$ stateChangeSuccess (3认同)