$ stateChangeStart事件在状态更改后继续

时间:2014-12-17 18:31:53

标签: angularjs angular-ui-router

我试图将用户发送到特定的“关闭”状态。 Angular中的UI状态使用以下内容:

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
  // check the destination is active
  if(toState.data.isClosed) { // note that the 'closed' state has isClosed set to false
    event.preventDefault();
    $state.go('closed');
  }
  $rootScope.data = toState.data;  // getting executed twice after our state transition to 'closed'
  $log.debug(toState);
});

我遇到的问题是$rootScope.data = toState.data在我们过渡到“关闭”状态后被调用两次。州。

导航到我们的订单时第一次执行$startChangeStart&#39}在路由器中设置data.isClosed = true的状态,状态将更改为“已关闭”状态。并且有问题的代码没有被执行。

因为我们正在改变状态以关闭'现在,$startChangeStart再次被触发,并且有问题的代码第一次执行,而toState是我们关闭的'州。

奇怪的是,随后执行代码,从if()逻辑开始,toState是原始状态' order' ...意味着当所有内容都被加载时,$ rootScope.data变量包含来自' order'的数据。而不是关闭'。添加一些断点和上面的调试代码就可以确认。

有任何解释吗?

更新

由于执行模式状态转换为“关闭”状态。状态,我已添加一个返回以确保$state.go()呼叫终止后继续执行。修改后的代码:

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
  // check the destination is active
  if(toState.data.isClosed) { // note that the 'closed' state has isClosed set to false
    event.preventDefault();
    $state.go('closed');
    return;
  }
  $rootScope.data = toState.data;  // getting executed twice after our state transition to 'closed'
  $log.debug(toState);
});

现在按预期工作,但我不确定它是否正确#。

1 个答案:

答案 0 :(得分:2)

带有return语句的解决方案很简单。我创建了this playground,您可以在那里测试它。

让我们拥有这些状态。首先是一些isClosed为false的状态 - 不应该由我们的事件监听器管理

  .state('state1', {
    url: "/state1",
    template: "<div>this is a state1</div>",
    data: { isClosed : false },
  })
  .state('state2', {
    url: "/state2",
    template: "<div>this is a state2</div>",
    data: { isClosed : false },
  })

这些将被捕获并重定向

  .state('stateClosed1', {
    url: "/stateClosed1",
    template: "<div>this is a stateClosed1</div>",
    data: { isClosed : true },
  })
  .state('stateClosed2', {
    url: "/stateClosed2",
    template: "<div>this is a stateClosed2</div>",
    data: { isClosed : true },
  })
  // even this would be handy
  .state('closed', {
    url: "/closed",
    template: "<div>this is a closed</div>",
    data: { isClosed : false },
  })

现在,无论何时我们前往任何州,都会触发 $stateChangeStart 事件。因此,如果我们进入“未处理”状态(state1,state2) - 事件将被触发一次。

如果我们去处理状态(stateClosed1,stateClosed2),事件总是被触发两次:

  • 转到stateClosed1
  • 关闭

只是为了确定:事件真的被解雇了两次。这就是为什么我们应该写这些听众而不是像(尽快离开)

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

    // get out if we already go to state, which is about to be handled below
    if(toState.name === "closed") {
      return;
    }

    // check the destination is active
    if (toState.data.isClosed) { // note that the 'closed' 
      event.preventDefault();    // state has isClosed set to false 
      $state.go('closed');
      return; 
    }
    $rootScope.data = toState.data; // getting executed 'closed'
                                    // twice after our state transition to 
                                    // only if above if does not contain return
    console.debug(toState);
  });

事实上,这个解决方案(尽快退出)是这些Q&amp;答: