在回答here之后,我有以下代码:
.directive('confirmOnExit', function($window) {
return {
scope: {},
link: function(scope) {
var message = "Changes you made may not be saved.";
$window.onbeforeunload = function(){
return message;
};
scope.$on('$locationChangeStart', function(event) {
if(!$window.confirm("Do you want to leave this page? "+message))
event.preventDefault();
});
scope.$on('$destroy',function(){
$window.onbeforeunload = null;
});
}
};
})
在Chrome上,一切都很好。但是,在Firefox上,几乎每次单击确认对话框的按钮时,都会发生错误:
Error: [$rootScope:inprog] $digest already in progress
我在网上找到的解决方案大多建议使用$timeout
。但是,event.preventDefault()
函数中的$timeout
似乎无法阻止URL更改。我该怎么办?
答案 0 :(得分:0)
我刚遇到同样的问题。对我来说,调用确认会导致firefox和IE出错。为了解决这个问题,如果有要显示的消息,我会立即阻止默认,并在超时时运行确认。然后,如果用户点击“离开页面”,我清除onbeforeunload并使用$ location服务再次设置网址。如果您的应用是单页应用,则会在首页加载时调用$ locationChangeStart,因此您需要在顶部添加标记,如:if (!hasLoaded) { hasLoaded = true; return; }
$rootScope.$on('$locationChangeStart', function (e, newUrl, oldUrl) {
// Call the function and show the confirm dialogue if necessary
if ($window.onbeforeunload) {
let message = $window.onbeforeunload();
if (message) {
// Since we're going to show a message, cancel navigation
e.preventDefault();
$timeout(() => {
if (confirm(message)) {
// User chose not to stay. Unregister the function so that it doesn't fire again.
$window.onbeforeunload = undefined;
// Run the url again. We've cleared onbeforeunload, so this won't create a loop
$location.url(newUrl.replace($window.location.protocol + '//' + $window.location.host, ''));
}
});
}
}
})