UI路由器解决过程中应用加载微调 [英] Apply loading spinner during ui-router resolve

查看:150
本文介绍了UI路由器解决过程中应用加载微调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

决心 $ routeProvider 的属性允许之前对应的视图渲染来执行一些工作。

resolve property of $routeProvider allows to execute some jobs BEFORE corresponding view is rendered.

如果我想显示一个微调,而那些作业,以增加用户体验的执行怎么办?结果
事实上,否则用户会觉得应用程序已经因为没有视图元素被用于显示例如几毫秒> 600阻塞。

What if I want to display a spinner while those jobs are executed in order to increase user experience?
Indeed, otherwise the user would feel the application has been blocked since no view elements were displayed for some milliseconds > 600 for instance.

当然,还有就是定义一个全局 DIV 元素的方法的从当前视图,以显示微调感谢显示在 $范围。$ rootChangeStart 功能。结果
但是我并不想隐藏在中间只是一个可怜的微调整个页面。结果
我希望我的web应用程序的某些页面就显示加载的方式不同。

Of course, there was the way to define a global div element out of the current view to display in order to display the spinner thanks to the $scope.$rootChangeStart function.
But I don't want to hide the whole page with just a poor spinner in the middle.
I want some pages of my webapp differ regarding the way the loading is displayed.

我遇到来到我含上述确切问题,这个有趣的帖子

这方法导致一个可怕的UI体验。用户点击
  一个按钮刷新列表或什么的,整个画面变
  在一个通用的微调笼罩因为该库有没办法
  示只是对于那些实际上受视图(多个)旋转器
  状态的变化。不,谢谢。

That approach results in a horrible UI experience. The user clicks on a button to refresh a list or something, and the entire screen gets blanketed in a generic spinner because the library has no way of showing a spinner just for the view(s) that are actually affected by the state change. No thanks.

在任何情况下,在我提起这个问题,我认识到了解决
  特征是抗图案。它等待所有承诺解决
  然后动画状态的变化。这是完全错误的 - 你想
  状态之间的过渡动​​画运行并行数据
  负荷,以使后者可以由前盖起来。

In any case, after I filed this issue, I realised that the "resolve" feature is an anti-pattern. It waits for all the promises to resolve then animates the state change. This is completely wrong - you want your transition animations between states to run parallel to your data loads, so that the latter can be covered up by the former.

例如,假设你有一个项目列表,单击之一
  他们隐藏列表,显示了不同的看法该项目的详细信息。
  如果我们有一个异步加载该项目的细节需要,平均而言,
  400毫秒,那么我们就可以掩盖的负荷在大多数情况下,几乎完全
  有一个300ms的离开动画列表视图和一个300毫秒输入
  动画在项目详细信息视图。这样,我们提供了一个滑头的感觉
  到UI并能避免显示在大多数情况下都好手。

For example, imagine your have a list of items, and clicking on one of them hides the list and shows the item's details in a different view. If we have an async load for the item details that takes, on average, 400ms, then we can cover up the load almost entirely in most cases by having a 300ms "leave" animation on the list view, and a 300ms "enter" animation on the item details view. That way we provide a slicker feel to the UI and can avoid showing a spinner at all in most cases.

然而,这需要我们发起异步负载和状态
  在同一时刻改变的动画。如果我们用解决,那么
  整个异步动画时动画开始之前。用户
  点击,看到了微调,然后看见过场动画。整体
  状态变化将采取〜1000毫秒,这太慢了。

However, this requires that we initiate the async load and the state change animation at the same moment. If we use "resolve", then the entire async animation happens before the animation starts. The user clicks, sees a spinner, then sees the transition animation. The whole state change will take ~1000ms, which is too slow.

解决可能是之间的缓存依赖的有效途径
  如果它有选择不等待的承诺,但不同的看法
  目前的行为,总是在状态改变之前解决这些问题
  启动使得它几乎无用的,海事组织。它应避免任何
  涉及异步加载的依赖关系。

"Resolve" could be a useful way to cache dependencies between different views if it had the option not to wait on promises, but the current behaviour, of always resolving them before the state change starts makes it almost useless, IMO. It should be avoided for any dependencies that involve async loads.

我真的应该停止使用决心加载一些数据,而开始直接在相应的控制器装呢?所以,我可以为执行作业,只要更新相应的视图和地方,我希望在视图,而不是全局。

Should I really stop using resolve to load some data and rather start loading them in the corresponding controller directly? So that I can update the corresponding view as long as the job is executed and in the place I want in the view, not globally.

推荐答案

您可以使用监听 $ routeChangeStart 和示例显示元素时,它触发一个指令:

You can use a directive that listens on $routeChangeStart and for example shows the element when it fires:

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);
    }
  };
});

然后你将它放在特定视图的装载机,例如:

Then you place it on the specific view's loader, for example:

查看1:

<div show-during-resolve class="alert alert-info">
  <strong>Loading.</strong>
  Please hold.
</div>

查看2:

<span show-during-resolve class="glyphicon glyphicon-refresh"></span>

这个解决方案(以及与此有关的许多其他解决方案)的问题是,如果你浏览到从外部站点的途径之一会有未装入previous NG-视图模板,让你的页面可能只是要解决过程中的空白。

The problem with this solution (and many other solutions for that matter) is that if you browse to one of the routes from an external site there will be no previous ng-view template loaded, so your page might just be blank during resolve.

这可以通过创建一个指令,将作为后备装载来解决。它会监听 $ routeChangeStart ,并显示出装载机仅如果没有previous路线。

This can be solved by creating a directive that will act as a fallback-loader. It will listen for $routeChangeStart and show a loader only if there is no previous route.

有一个基本的例子:

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');
      });
    }
  };
});

回退加载器将被放置在元素之外与NG-观点:

The fallback loader would be placed outside the element with ng-view:

<body>
  <resolve-loader></resolve-loader>
  <div ng-view class="fadein"></div>
</body>

这一切演示: http://plnkr.co/edit/7clxvUtuDBKfNmUJdbL3?p=$p$pview

这篇关于UI路由器解决过程中应用加载微调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆