Можно ли определить, что пользователь вошел на страницу с помощью кнопки возврата истории в своем браузере? Предпочтительно я хочу обнаружить это действие с помощью angular.js.
Я не хочу использовать угловую маршрутизацию. Он также должен работать, если пользователь отправляет форму, и после успешной отправки на сервер и перенаправления это также должно быть возможно, если пользователь вернется к форме с помощью кнопки возврата в браузере.
источник
$locationChangeSuccess
срабатывает событие после$watch
обратного вызова. Но при изменении URL-адреса с помощью кнопки назад / вперед илиhistory.back()
api$locationChangeSuccess
событие запускается перед$watch
обратным вызовом. Поэтому, когда срабатывание обратного вызова часовactualLocation
уже равноnewLocation
. Это то, как angular работает внутри, и это решение просто использует это внутреннее поведение./#/news/?page=2
до/#/news/?page=3
. Чтобы поймать их, вы также можете использовать$location.absUrl()
вместо$location.path()
(в обоих местах, где он используется выше).Если вам нужно более точное решение (обнаружение вперед и назад), я расширил решение, предоставленное Бертраном :
$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++; } } });
источник
Для ui-routing я использую приведенный ниже код.
Внутри
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; });
Вы можете получить значение 'previousState' в событии '$ stateChangeSuccess' также следующим образом, если хотите.
$rootScope.$on("$stateChangeSuccess", function (event, toState, toParams, fromState, fromParams) { $rootScope.previousStatus = fromState.name; });
источник
Я знаю, что это старый вопрос. В любом случае :)
Ответ Бемы выглядит великолепно. Однако, если вы хотите, чтобы он работал с `` нормальными '' 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?'); } }); });
источник
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источник
Итак, я переписал ответ @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
переменной. Оттуда вы можете делать все, что захотите, как и в исходном коде. Со своей стороны, я бы подумал о трансляции события, чтобы отдельные контроллеры могли делать все, что они должны, но вы могли бы включить глобальные действия, если бы это было необходимо .Спасибо за отличный ответ, и я надеюсь, что это поможет другим пользователям машинописного текста.
источник
Мое решение этой проблемы -
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 не запускается.
источник