ServiceNow环境下$locationChangeStart调用preventDefault后如何恢复重定向
问题解答
核心误区说明
e.preventDefault() 仅对当前单次触发的事件实例生效,调用后无法撤销本次事件的阻止效果。你之前的两个尝试均不符合逻辑:
$().unbind(preventDefault)是jQuery的事件解绑方法,既没有指定目标事件名,也没有传入正确的监听函数引用,和AngularJS的$rootScope事件监听机制完全不匹配。e.returnValue = true是DOM原生事件的兼容属性,且仅在事件执行流程中修改才有效,你放在$timeout里执行时,本次$locationChangeStart事件已经处理完毕,修改已结束的事件对象属性没有任何作用。
正确实现方案
你只需要给事件监听加一个状态开关,控制是否执行阻止逻辑即可,不需要操作已触发的事件对象,也不需要解绑事件:
var originalUrl, initUrl; // 新增状态开关:默认开启跳转阻止 var shouldPreventLocationChange = true; $rootScope.$on("$locationChangeStart", function(e, newUrl){ if(newUrl != originalUrl && newUrl != initUrl && c.count < c.maxCount ){ $window.history.replaceState(newUrl, $document.title, newUrl); c.count++; } originalUrl = newUrl; // 仅开关开启时才阻止跳转 if(shouldPreventLocationChange){ e.preventDefault(); } }); $timeout(function(){ console.log("恢复默认跳转逻辑"); // 关闭开关后,后续所有$locationChangeStart事件都走默认处理逻辑 shouldPreventLocationChange = false; }, 2000); $scope.changeURL = function(){ initUrl = $location.absUrl(); var params = $location.search(); params.o = $scope.data.sort_fields; params.d = $scope.data.sort_direction; params.initial_load = true; // 触发$locationChangeStart事件 $location.search($httpParamSerializer(params)); } $scope.changeURL();
逻辑说明
- 开关
shouldPreventLocationChange开启期间,所有URL跳转都会被阻止,配合replaceState实现修改URL不刷新页面的需求,不影响你原有计数逻辑的执行。 - 2秒后开关自动关闭,后续所有URL跳转都会走AngularJS默认的处理逻辑,不需要额外操作事件对象。
- 该实现完全兼容ServiceNow实例的AngularJS运行环境,没有使用特殊语法。
内容的提问来源于stack exchange,提问作者Meeshaill
相关产品推荐
相关产品推荐

