无法重置stateChangeStart侦听器

时间:2015-04-14 14:35:36

标签: angularjs angular-ui-router

在我的应用程序的根目录中,我有以下监听器来检查身份验证/

  $rootScope.setStateChangeDefault = function(){
    $rootScope.$on('$stateChangeStart', function(ev, to, toParams, from, fromParams) {
      ... check User Authentication
    });
  }
  $rootScope.setStateChangeDefault();

然后,在用户必须保存的页面的控制器中,我有以下内容:

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ 
  if($scope.form.modified){
    var response = confirm('Are you sure you want to exit without saving?');

    if(response){
      $rootScope.setStateChangeDefault();
      $state.go(toState,toParams);
    }else{
      event.preventDefault();
    }
  }
  else{
    $rootScope.setStateChangeDefault();
    $state.go(toState,toParams);
  }
});

当表单数据变脏时,系统会询问用户是否要保存。那部分有效。但是$ root.setStateChangeDefault在控制器中什么都不做。它应该设置原始回调,然后尝试再次设置状态,但是,每次用户尝试从该点开始更改状态时,都会给出提示。为什么回调没有像初始化那样重新设置为默认值?

2 个答案:

答案 0 :(得分:3)

几乎没有必要的问题。这些至关重要,它们可能会导致内存泄漏。

我创建了working plunker here

首先,我不确定 setStateChangeDefault() 。如果我们需要挂钩$stateChangeStart,我们应该像这样做

$rootScope.setStateChangeDefault = function() {
  // here we should not repeat to add listener
  //$rootScope.$on('$stateChangeStart', function(ev, to, toParams, from, fromParams) {
  // ... check User Authentication
  //});
}
$rootScope.setStateChangeDefault();

$rootScope.$on('$stateChangeStart', function(ev, to, toParams, from, fromParams) {
  // ... check User Authentication
});

换句话说,我们应该只添加一次监听器。不在一个被反复调用的方法内部

其次,如果我们在控制器内部调用它,我们肯定必须获取$rootSocpe.$on()注册的返回值。控制器反复实例化 - 这意味着一次又一次地调用$rootSocpe.$on()。为避免添加如此多的侦听器并造成内存泄漏,我们必须删除它们

// We MUST take this UN-Registration function reference
var removeIt = $rootScope.$on('$stateChangeStart'
  , function(event, toState, toParams, fromState, fromParams) {
     // content of this is discussed below
});

// and call it on controller destroy
$scope.$on('$destroy', removeIt);

最后,这应该是$on - $state.go()的内容。只是阻止默认或让它继续:

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

    if ($scope.form.$dirty) {
      var response = confirm('Are you sure you want to exit without saving?');

      if (response) {
        $rootScope.setStateChangeDefault();
        //$state.go(toState,toParams);
      } else {
        event.preventDefault();
      }
    } else {
      $rootScope.setStateChangeDefault();
      //$state.go(toState,toParams);
    }
  });

检查here

答案 1 :(得分:0)

因为我正在改变$rootScope对象,所以我不得不尝试找到一种方法来重置默认行为。对于我想要完成的事情,似乎最好的答案是使用$scope.$on('$stateChangeStart' ...而不是。当州改变时,这还有被摧毁的额外好处。所以最好的答案是:

$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ 
  if($scope.form.$dirty){
    var response = confirm('Are you sure you want to exit without saving?');
    if(!response){
      event.preventDefault();
    }
  }
});