有没有可能检测到用户是通过浏览器的后退按钮进入页面的?最好能够使用angular.js来检测这个操作。
我不想使用angular路由。如果用户提交表单并成功将其重定向到服务器,然后通过浏览器的后退按钮返回到表单,也应该能够检测到。
有没有可能检测到用户是通过浏览器的后退按钮进入页面的?最好能够使用angular.js来检测这个操作。
我不想使用angular路由。如果用户提交表单并成功将其重定向到服务器,然后通过浏览器的后退按钮返回到表单,也应该能够检测到。
下面是一个使用Angular的解决方案。
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?');
}
});
});
如果您需要更精确的解决方案(检测向前和向后),我对Bertrand提供的解决方案进行了扩展:
$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++;
}
}
});
$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的答案看起来很棒。然而,如果你想让它适用于“正常”的URL(没有哈希),你可以比较绝对路径,而不是$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?');
}
});
});
所以,我已经将@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
服务上创建属性,我们可以让我们的“on location change success”和“on location changed”代码都关闭本地actualLocation
变量。从那里开始,您可以像原始代码一样做任何您喜欢的事情。就我而言,我会考虑广播一个事件,以便各个控制器可以执行必要的操作,但如果必须的话,您也可以包括全局操作。
感谢您提供如此好的答案,我希望这能帮助其他TypeScript用户。
JavaScript有一个本地的history对象。
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
我对这个问题的解决方案是
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();
});
});
当按下返回按钮时,Angular 只触发 $routeChangeStart 事件,$locationChangeStart 不会被触发。
$locationChangeSuccess
事件会在$watch
回调之后触发。但是当 URL 使用“后退/前进”按钮或history.back()
API 改变时,$locationChangeSuccess
事件会在$watch
回调之前触发。因此,在$watch
回调触发时,actualLocation
已经等于newLocation
。这只是 Angular 内部工作的一种方式,而这个解决方案只是利用了这种内部行为。 - Ruslan Stelmachenko/#/news/?page=2
变为/#/news/?page=3
。为了捕获这些更改,您可以使用$location.absUrl()
替换$location.path()
(在上面使用它的两个地方)。 - Michael