本文介绍了$stateChangeStart 事件在状态改变后继续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以下方法将用户发送到 Angular 中的特定关闭"UI 状态:

I'm attempting to send the user to a specific 'closed' UI State in Angular using the following:

$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 在我们转换到关闭"状态后被调用两次.

The issue I'm having is that $rootScope.data = toState.data is getting called twice AFTER we've transitioned to the 'closed' state.

第一次 $startChangeStart 在导航到我们在路由器中设置的 data.isClosed = true 'order' 状态时执行,状态更改为 'closed' 并且有问题的代码不会被执行.

On the first time $startChangeStart executes when navigating to our 'order' state with data.isClosed = true set in the router, the state is changed to 'closed' and the code in question doesn't get executed.

当我们现在将状态更改为关闭"时,$startChangeStart 再次被触发,并且有问题的代码第一次执行,toState 是我们的关闭"状态.

As we are changing states to 'closed' now, $startChangeStart gets triggered again, and the code in question executes for the first time with toState being our 'closed' state.

奇怪的是,代码随后被执行,在 if() 逻辑之后开始,toState 是 'order' 的原始状态......意味着当一切都加载完毕时, $rootScope.data 变量包含来自订单"而不是关闭".加了几个断点,上面的调试代码就确认了.

Strangely, the code is then subsequently executed, starting after the if() logic with toState being the original state of 'order'... meaning that when everything is loaded up, the $rootScope.data variable contains the data from 'order' rather than 'closed'. Adding a few breakpoints and the debugging code above confirms.

有什么解释吗?

更新

由于状态转换为关闭"状态的执行模式,我添加了一个 return 以确保在 $state.go() 调用后继续执行被终止.修改后的代码:

Due to the execution pattern with the state transition to the 'closed' state, I've added a return to ensure that the continued execution after the $state.go() call is terminated. Revised code:

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

这现在按预期工作,但我不确定它是否正确".

This is now working as expected, but I'm not sure it's 'correct'.

推荐答案

带有 return 语句的解决方案简单正确.我创建了这个游乐场,您可以在其中进行测试.

The solution with return statement is simple correct. I created this playground, where you can test that.

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

Let's have these states. Firstly some state with isClosed false - which should not be managed by our event listener

  .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) - 事件将被触发一次.

Now, whenever we go to any state, the event $stateChangeStart is fired. So if we go to "not handled" states (state1, state2) - the event will be triggered once.

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

If we go to handled states (stateClosed1, stateClosed2), event is fired always twice:

  • 转到 stateClosed1
  • 转到已关闭

可以肯定的是:该事件确实被触发了两次.这就是为什么我们应该像这样编写这些监听器(尽快离开):

Just to be sure: the event is really fired twice. And that's why we should write these listeners rather like this (get out ASAP):

  $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 & 中的问题.答:

In fact, this solution (getting out as soon as possible), was issue in these Q & A:

这篇关于$stateChangeStart 事件在状态改变后继续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 19:03