jQuery 如何使用角度检测浏览器后退按钮单击事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15813850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to detect browser back button click event using angular?
提问by Thomas Kremmel
Is it possible to detect that a user entered a page through using the history back button in his browser? Preferably I want to detect this action using angular.js.
是否可以检测到用户通过使用浏览器中的历史后退按钮进入了页面?最好我想使用 angular.js 检测这个动作。
I do not want to use angular routing. It should also work if a user submits a form and after a successful submit to the server and a re-direct, it should also be possible if the user goes back to the form using the back button of the browser.
我不想使用角度路由。如果用户提交表单并在成功提交到服务器并重定向后,它也应该可以工作,如果用户使用浏览器的后退按钮返回表单也应该是可能的。
回答by Bertrand
Here is a solution with 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?');
}
});
});
I am using a run block to kickstart this. First I store the actual location in $rootScope.actualLocation, then I listen to $locationChangeSuccess and when it happens I update actualLocation with the new value.
我正在使用运行块来启动它。首先我将实际位置存储在 $rootScope.actualLocation 中,然后我听 $locationChangeSuccess 并且当它发生时我用新值更新 actualLocation。
In the $rootScope I watch for changes in the location path and if the new location is equal to previousLocation is because the $locationChangeSuccess was not fired, meaning the user has used the history back.
在 $rootScope 中,我观察位置路径的变化,如果新位置等于 previousLocation 是因为 $locationChangeSuccess 没有被触发,这意味着用户已经使用了历史记录。
回答by Mariusz Karpicki
If you want more precise solution (detecting back and forward) I extended solution delivered by Bertrand:
如果您想要更精确的解决方案(检测前后检测),我扩展了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++;
}
}
});
回答by harish polanki
For ui-routing, I'm using the below code.
对于 ui 路由,我使用以下代码。
Inside App.run()
, use
在里面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;
});
You can get the 'previousState' value in '$stateChangeSuccess' event also like as follows if `you want.
如果你愿意,你也可以在 '$stateChangeSuccess' 事件中获得 'previousState' 值,如下所示。
$rootScope.$on("$stateChangeSuccess", function (event, toState, toParams, fromState, fromParams)
{
$rootScope.previousStatus = fromState.name;
});
回答by Jahongir Rahmonov
I know it is an old question. Anyways :)
我知道这是一个老问题。无论如何 :)
Bema's answer looks great. However, if you want to make it work with 'normal' urls (without hash I guess), you could compare absolute path, instead of the one returned by $location.path()
:
Bema 的回答看起来很棒。但是,如果您想让它使用“普通”网址(我猜没有哈希),您可以比较绝对路径,而不是由以下返回的路径$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?');
}
});
});
回答by Andrew Gray
So, I've transcribed the answer by @Bema into TypeScript, and this is what it looks like:
所以,我已经将@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);
}
We don't have to create a property off of the $rootScope
service, we can just have our 'on location change success' and 'on location changed' code both close over the local actualLocation
variable. From there, you can do whatever you like, just as in the original code. For my part, I'd consider broadcasting an event so that individual controllers can do whatever they must, but you could include global actions if you had to.
我们不必在$rootScope
服务之外创建属性,我们只需将“位置更改成功”和“位置更改”代码都关闭在局部actualLocation
变量上即可。从那里,您可以随心所欲,就像在原始代码中一样。就我而言,我会考虑在播放事件使个别控制器可以为所欲为必须的,但你可以包括全球行动,如果你要。
Thanks for the great answer, and I hope this helps other typescript users out there.
感谢您的出色回答,我希望这可以帮助其他打字稿用户。
回答by Andrew Gray
JavaScript has a native history object.
JavaScript 有一个本地历史对象。
window.history
Check the MDN for more info; https://developer.mozilla.org/en-US/docs/DOM/window.history?redirectlocale=en-US&redirectslug=window.history
查看 MDN 以获取更多信息;https://developer.mozilla.org/en-US/docs/DOM/window.history?redirectlocale=en-US&redirectslug=window.history
Not sure how good it's on multi-browser support tho.
不确定它在多浏览器支持方面有多好。
Update
更新
Seems what I've called above is only for Gecko-type browsers.
似乎我上面所说的仅适用于 Gecko 类型的浏览器。
For other browsers try to use history.js
; https://github.com/browserstate/history.js
对于其他浏览器尝试使用history.js
; https://github.com/browserstate/history.js
回答by syraz37
My Solutio to this problem is
我对这个问题的解决方案是
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();
});
});
回答by bullgare
when pressing back button, angular fires only $routeChangeStartevent, $locationChangeStartnot fired.
当按下后退按钮时,angular 只触发$routeChangeStart事件,不触发$locationChangeStart。