如何检测浏览器返回按钮点击事件使用角度?

是否可以通过浏览器中的历史回退按钮来检测用户是否输入了页面?我最好使用 angular.js 来检测这个动作。

我不想使用角度路由。如果用户提交了一个表单,在成功地向服务器提交并重定向之后,如果用户使用浏览器的后退按钮返回到表单,那么它也应该可以工作。

94783 次浏览

JavaScript 有一个本机历史对象。

window.history

检查 MDN 获取更多信息; https://developer.mozilla.org/en-US/docs/DOM/window.history?redirectlocale=en-US&redirectslug=window.history

不知道它对多浏览器的支持有多好。

更新

看起来我上面所说的只适用于 Gecko 类型的浏览器。

对于其他浏览器,请尝试使用 history.js; https://github.com/browserstate/history.js

这里有一个关于角度的解决方案。

myApp.run(function($rootScope, $route, $location){
//Bind the `$locationChangeSuccess` event on the rootScope, so that we dont need to
//bind in induvidual controllers.


$rootScope.$on('$locationChangeSuccess', function() {
$rootScope.actualLocation = $location.path();
});


$rootScope.$watch(function () {return $location.path()}, function (newLocation, oldLocation) {
if($rootScope.actualLocation === newLocation) {
alert('Why did you use history back?');
}
});
});

我正在使用一个运行块来启动这个。首先,我将实际位置存储在 $rootScope.actialLocation 中,然后侦听 $locationChangeSuccess,当这种情况发生时,我将使用新值更新 realalLocation。

在 $rootScope 中,我观察位置路径的变化,如果新位置等于前一个位置,那是因为 $locationChangeSuccess 没有触发,这意味着用户已经返回使用了历史记录。

当按下返回按钮时,角度发射只有 $routeChangeStart事件,$locationChangeStart不发射。

如果你想要更精确的解决方案(前后检测) ,我扩展了 伯特兰提供的解决方案:

$rootScope.$on('$locationChangeSuccess', function() {
$rootScope.actualLocation = $location.path();
});




$rootScope.$watch(function () {return $location.path()}, function (newLocation, oldLocation) {


//true only for onPopState
if($rootScope.actualLocation === newLocation) {


var back,
historyState = $window.history.state;


back = !!(historyState && historyState.position <= $rootScope.stackPosition);


if (back) {
//back button
$rootScope.stackPosition--;
} else {
//forward button
$rootScope.stackPosition++;
}


} else {
//normal-way change of page (via link click)


if ($route.current) {


$window.history.replaceState({
position: $rootScope.stackPosition
});


$rootScope.stackPosition++;


}


}


});

我知道这是个老问题了

Bema 的回答看起来很棒。然而,如果你想让它与“正常”url 一起工作(我猜没有 hash) ,你可以比较绝对路径,而不是 $location.path()返回的那个:

myApp.run(function($rootScope, $route, $location){
//Bind the `$locationChangeSuccess` event on the rootScope, so that we dont need to
//bind in induvidual controllers.


$rootScope.$on('$locationChangeSuccess', function() {
$rootScope.actualLocation = $location.absUrl();
});


$rootScope.$watch(function () {return $location.absUrl()}, function (newLocation, oldLocation) {
if($rootScope.actualLocation === newLocation) {
alert('Why did you use history back?');
}
});
});

我对这个问题的解决方案是

app.run(function($rootScope, $location) {
$rootScope.$on('$locationChangeSuccess', function() {
if($rootScope.previousLocation == $location.path()) {
console.log("Back Button Pressed");
}
$rootScope.previousLocation = $rootScope.actualLocation;
$rootScope.actualLocation = $location.path();
});
});

对于 ui 路由,我使用以下代码。

App.run()内部,使用

 $rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams)
{


if (toState.name === $rootScope.previousState )
{
// u can any 1 or all of below 3 statements
event.preventDefault();  // to Disable the event
$state.go('someDefaultState'); //As some popular banking sites are using
alert("Back button Clicked");


}
else
$rootScope.previousState= fromState.name;
});

如果需要,您可以在“ $stateChangeSuccess”事件中获取“ previousState”值,如下所示。

    $rootScope.$on("$stateChangeSuccess", function (event, toState, toParams, fromState, fromParams)
{


$rootScope.previousStatus = fromState.name;
});

所以,我已经把@Bema 的答案转换成了 TypeScript,它看起来是这样的:

namespace MyAwesomeApp {
// ReSharper disable once Class
function detectBackButton(
$rootScope: ng.IRootScopeService,
$location: ng.ILocationService
) {
let actualLocation: string = '';


$rootScope.$on('$locationChangeSuccess',
() => {
actualLocation = $location.path();
});


$rootScope.$watch(() => $location.path(),
(newLocation: string, oldLocation: string) => {
if (actualLocation === newLocation) {
//$rootScope.$broadcast('onBackButtonPressed', null);
}
});
}


detectBackButton.$inject = [
'$rootScope',
'$location'
];


angular
.module('app')
.run(detectBackButton);
}

我们不需要在 $rootScope服务上创建属性,我们只需要在本地 actualLocation变量上关闭‘ on location change Success’和‘ on location change’代码。在那里,您可以做任何您喜欢的事情,就像在原始代码中一样。就我而言,我会考虑广播一个事件,这样单个控制器就可以做任何它们必须做的事情,但是您可以包括全局操作 如果有必要的话

谢谢你的回答,我希望这对其他打字用户有所帮助。