为什么这个 Angular ui 路由器代码会导致 $digest 中的无限循环? [英] Why does this Angular ui router code cause an infinite loop in $digest?

查看:30
本文介绍了为什么这个 Angular ui 路由器代码会导致 $digest 中的无限循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尽可能地简化了代码.关于嵌套状态和事件处理/广播的一些事情导致了无限循环.在 Chrome 中,我可以暂停它并看到它在 Angular 的 $digest 函数中永远循环.知道为什么吗?这是我的示例代码中的错误,还是 Angular 中的错误,或者 UI 路由器?

<html ng-app='bugapp' ng-controller='BugAppCtrl'><头><script src='//code.jquery.com/jquery-1.10.1.min.js'></script><!-- Angular 1.2.11 --><script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js'></script><!-- UI 路由器 0.2.8 --><script src='//cdn.jsdelivr.net/angular.ui-router/0.2.8/angular-ui-router.js'></script><脚本>angular.module('bugapp', ['ui.router']).run(function ($rootScope, $state, $stateParams) {$rootScope.$state = $state;$rootScope.$stateParams = $stateParams;}).config(function ($locationProvider, $stateProvider, $urlRouterProvider) {$locationProvider.html5Mode(false);$stateProvider.state(根",{摘要:真实,url: "/servletContext?asUser",模板:'<div ui-view></div>'//???}).state("root.home", {摘要:真实,网址:/家",模板:<div ng-if='hasData()' ui-view ></div>"}).state("root.home.profile", {网址:/个人资料",模板:'

whatever

'})}).controller('BugAppCtrl', function ($scope, $state, $stateParams, $log, $location) {$log.log('BugAppCtrl: 构造函数');$scope.hasData = function() {var res = !!$scope.foo;//$log.log("hasData 被调用,返回" + res + " foo is " + $scope.foo);返回资源;};$scope.$on('$stateChangeSuccess', function () {$log.log("状态改变了!(" + $state.current.name + ")");$scope.foo = '垃圾';$scope.$broadcast("resetfoo");});$state.go('root.home.profile');});<身体><div ui-view></div></html>

解决方案

我怀疑这是 UI Router 中的一个错误,原因有两个:

  1. 我尝试了您的代码,然后尝试降级 UI 版本路由器到 0.2.7.当我使用 0.2.7 时,它起作用了.
  2. 即使您继续使用 UI Router 0.2.8 版本,如果您通过 $location 而不是 $state 执行状态更改,它也可以工作.这是使用 $location 而不是 $state.go 调用的示例:

    $location.path('/servletContext/home/profile');

虽然我使用并推荐UI Router(没有嵌套视图是不行的),如果你以后发现你想要在用户尝试去某些页面时做任何拦截或重定向,我推荐使用$location.path 而不是 $state,原因我描述了 在博文中

编辑:我之前没有尝试过参数,只是尝试过使用您发布的代码(我创建了第二个控制器并将其分配给您的root.home.profile"状态),并且有用.UI 路由器的说明位于此处.但基本上,如果您在状态定义中设置 URL 的方式与使用 UI Router 的方式相同:

url: "/profile/:foo",

然后在您的 $location.path 调用中添加路径中的参数:

$location.path('/servletContext/home/profile/12');

并且您可以从

访问控制器中的 12

$stateParams.foo

I've boiled the code down as much as I can. Something about nested states and the event handling/broadcasting is causing an infinite loop. In Chrome I can pause it and see that it is looping forever in Angular's $digest function. Any idea why? Is it a bug in my example code, or a bug in Angular, or the UI Router?

<!doctype html>
<html ng-app='bugapp' ng-controller='BugAppCtrl'>
<head>
  <script src='//code.jquery.com/jquery-1.10.1.min.js'></script>

  <!-- Angular 1.2.11 -->
  <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js'></script>

  <!-- UI router 0.2.8 -->
  <script src='//cdn.jsdelivr.net/angular.ui-router/0.2.8/angular-ui-router.js'></script>

  <script>
angular.module('bugapp', ['ui.router'])
  .run(function ($rootScope, $state, $stateParams) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
  })
  .config(function ($locationProvider, $stateProvider, $urlRouterProvider) {
    $locationProvider.html5Mode(false);

    $stateProvider
      .state("root", {
        abstract: true,
        url: "/servletContext?asUser",
        template: '<div ui-view></div>'  // ???
      })
      .state("root.home", {
        abstract: true,
        url: "/home",
        template: "<div ng-if='hasData()' ui-view ></div>"

      })
      .state("root.home.profile", {
        url: "/profile",
        template: '<div>whatever</div>'
      })

  })
  .controller('BugAppCtrl', function ($scope, $state, $stateParams, $log, $location) {
    $log.log('BugAppCtrl: constructor');

    $scope.hasData = function() {
      var res = !!$scope.foo;
      // $log.log("hasData called, returing " + res + " foo is " + $scope.foo);
      return res;
    };

    $scope.$on('$stateChangeSuccess', function () {
      $log.log("State changed! (to " + $state.current.name + ")");
      $scope.foo = 'junk';
      $scope.$broadcast("resetfoo");
    });

    $state.go('root.home.profile');
  });
  </script>
</head>
<body>
  <div ui-view></div>
</body>
</html>

解决方案

I suspect this is a bug in the UI Router, for two reasons:

  1. I tried your code and then tried downgrading the version of UI Router to 0.2.7. When I used 0.2.7, it worked.
  2. Even if you keep using version 0.2.8 of UI Router, if you perform the state change through $location instead of $state, it works. Here's an example of using $location instead of the $state.go call:

    $location.path('/servletContext/home/profile');
    

Although I use and recommend UI Router (can't do without nested views), if you find in the future that you want to do any sort of intercepting or redirecting when the user tries to go to certain pages, I recommend using $location.path instead of $state, for reasons I described in a blog post

Edit: I haven't tried with parameters before but just tried with the code you posted (I created a 2nd controller and assigned it to your 'root.home.profile' state), and it works. Instructions from UI Router are here. But basically if you set your URL in your state definition the same way you would with UI Router:

url: "/profile/:foo",

then in your $location.path call add the parameter in the path:

$location.path('/servletContext/home/profile/12');

and you can access the 12 in the controller from

$stateParams.foo

这篇关于为什么这个 Angular ui 路由器代码会导致 $digest 中的无限循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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