问题描述
我正在尝试使用以下方法将用户发送到 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 事件在状态改变后继续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!