Javascript AngularJS在路线变更前确认
是否可以侦听路由更改和onwindowunload以确认页面离开而不保存更改 用例:Javascript AngularJS在路线变更前确认,javascript,angularjs,Javascript,Angularjs,是否可以侦听路由更改和onwindowunload以确认页面离开而不保存更改 用例: 用户点击 用户在浏览器中按下后退按钮 不同URL中的用户类型 如果用户单击“取消”,则停止页面/路线更改 我看到了一些不同的例子,但没有一个是完全正确的。您会发现$locationChangeStart是一个事件,您可以通过监听来检测路由更改 试试像这样的东西 $rootScope.$on('$locationChangeStart', function (event, next, current) {
- 用户点击
- 用户在浏览器中按下后退按钮
- 不同URL中的用户类型
我看到了一些不同的例子,但没有一个是完全正确的。您会发现
$locationChangeStart
是一个事件,您可以通过监听来检测路由更改
试试像这样的东西
$rootScope.$on('$locationChangeStart', function (event, next, current) {
/* do some verification */
});
$route.reload()
将阻止路由更改
用户单击后退或更改url等之间的区别不会产生影响。由于浏览器在更改url超过#
时不会重新加载任何资源,因此所有内容仍然包含在您的角度逻辑中。这意味着所有这些方法都应该触发$locationChangeStart
事件
@乔恩指出,
$route
服务肯定会对你有用。.reload()
方法将阻止路由更改的完成,但是如果您仔细查看,$route
服务可以做更多的事情-请参阅。我只想在$rootScope上维护一个属性,比如hasunaveddiets
function confirmLeavePage(e) {
var confirmed;
if ($rootScope.hasUnsavedEdits) {
confirmed = $window.confirm("You have unsaved edits. Do you wish to leave?");
if (e && !confirmed) {
e.preventDefault();
}
}
}
$window.addEventListener('beforeunload', confirmLeavePage);
$rootScope.$on("$locationChangeStart", confirmLeavePage);
您可能需要稍微调整代码以处理这两种情况。有关详细信息,请参见演示:
在演示中,如果您更改输入的值,则在尝试返回时会引起注意
收听$locationChangeStart
并使用event.preventDefault()
在更改未确认时取消位置更改
与
$route.reload()
相比,此方法有一个优点:当前控制器和模型不会重新实例化。因此,当用户单击“后退”按钮时,所有变量都保持不变。我创建了以下服务,其中包含了其他答案中给出的信息(CoffeeScript,请参阅):
它基于angular ui路由器(使用$state
服务)。当您的网站进入数据可能丢失的状态时,您需要拨打
ChangeLossPreventer.prevent("Optional warning message.");
如果存在此状态(即用户保存数据),则需要调用:
ChangeLossPreventer.cancel()
默认情况下,警告将出现在状态更改或页面关闭时(即刷新或转到其他网站)。您可能还需要验证执行其他操作是否安全(即,如果存在未保存的更改,则不要使用XHR注销):
我已经创建了一个模拟它的
export default class myRouteController {
constructor($scope, $window) {
this.$scope = $scope;
this.$window = $window;
this.$scope.$on('$stateChangeStart', (evt) => {
if(this.form.$dirty && !$window.confirm('Are you sure you want to leave this page?')) {
evt.preventDefault();
}
});
}
}
一定要退房。。您可能希望利用某些事件。@LawerenceJones一些注意事项:$route.reload()不会停止页面更改。当在浏览器中键入其他url时,这不起作用,我想我也需要执行
onunload
。您确定只编辑url中超出#
的部分吗?我现在已经在chrome上测试了它,它在那个事件中得到了提升。我应该澄清,$route.reload
只会重新加载当前路由,因此首先会阻止路由更改。另外,仅供参考-我发现$routeChangeStart是不可取消的,+1表示$locationChangeStart这也不会阻止页面更改。具体是什么不起作用?confirmLeavePage
是否点火?$window.confirm是否会弹出一条消息?如果我执行类似以下操作会怎么样:$location.path('config/'+$routeParams.id)
这仍然有效吗?@amcdnl我没有尝试,但您可以通过将锚定标记的herf
更改为ng单击
并重试来测试它。当用户使用ui sref指令单击锚定时,这不适用于我的情况。在这种情况下,locationChangeStart是在状态更改后触发的。
$scope.logout = function() {
// confirmation will pop up only if there are unsaved changes
ChangeLossPreventer.prompt().then(function(){
// logout after confirmation
});
};
function init() {
//initialize data here..
//Make sure they're warned if they made a change but didn't save it
//Call to $on returns a "deregistration" function that can be called to
//remove the listener (see routeChange() for an example of using it)
onRouteChangeOff = $rootScope.$on('$locationChangeStart', routeChange);
}
function routeChange(event, newUrl) {
//Navigate to newUrl if the form isn't dirty
if (!$scope.editForm.$dirty) return;
var modalOptions = {
closeButtonText: 'Cancel',
actionButtonText: 'Ignore Changes',
headerText: 'Unsaved Changes',
bodyText: 'You have unsaved changes. Leave the page?'
};
modalService.showModal({}, modalOptions).then(function (result) {
if (result === 'ok') {
onRouteChangeOff(); //Stop listening for location changes
$location.path(newUrl); //Go to page they're interested in
}
});
//prevent navigation by default since we'll handle it
//once the user selects a dialog option
event.preventDefault();
return;
}
export default class myRouteController {
constructor($scope, $window) {
this.$scope = $scope;
this.$window = $window;
this.$scope.$on('$stateChangeStart', (evt) => {
if(this.form.$dirty && !$window.confirm('Are you sure you want to leave this page?')) {
evt.preventDefault();
}
});
}
}