Czy można wykryć, że użytkownik wszedł na stronę, korzystając z przycisku historii w przeglądarce? Najlepiej chcę wykryć tę akcję za pomocą angular.js.
Nie chcę używać frezowania kątowego. Powinno również zadziałać, jeśli użytkownik prześle formularz i po udanym przesłaniu na serwer i przekierowaniu, powinno być również możliwe, jeśli użytkownik wróci do formularza za pomocą przycisku wstecz w przeglądarce.
źródło
$locationChangeSuccess
zdarzenie jest uruchamiane po$watch
wywołaniu zwrotnym. Ale gdy zmieniasz adres URL za pomocą przycisku Wstecz /history.back()
Dalej lub interfejsu API,$locationChangeSuccess
zdarzenie jest uruchamiane przed$watch
wywołaniem zwrotnym. Kiedy więc odpalanie wywołania zwrotnego zegarkaactualLocation
jest już równenewLocation
. Po prostu działa wewnętrznie angular, a to rozwiązanie po prostu wykorzystuje to wewnętrzne zachowanie./#/news/?page=2
do/#/news/?page=3
. Aby je też złapać, możesz użyć$location.absUrl()
zamiast$location.path()
(w obu miejscach, w których jest używany powyżej).Jeśli chcesz bardziej precyzyjnego rozwiązania (wykrywanie wstecz i do przodu), rozszerzyłem rozwiązanie dostarczone przez firmę 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++; } } });
źródło
W przypadku routingu ui używam poniższego kodu.
Wewnątrz
App.run()
użyj$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; });
Możesz uzyskać wartość 'previousState' w zdarzeniu '$ stateChangeSuccess' również w następujący sposób, jeśli chcesz.
$rootScope.$on("$stateChangeSuccess", function (event, toState, toParams, fromState, fromParams) { $rootScope.previousStatus = fromState.name; });
źródło
Wiem, że to stare pytanie. Tak czy inaczej :)
Odpowiedź Bemy wygląda świetnie. Jeśli jednak chcesz, aby działało z `` normalnymi '' adresami URL (chyba bez hasha), możesz porównać ścieżkę bezwzględną, zamiast tej zwróconej przez
$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?'); } }); });
źródło
JavaScript ma natywny obiekt historii.
window.history
Sprawdź MDN, aby uzyskać więcej informacji; https://developer.mozilla.org/en-US/docs/DOM/window.history?redirectlocale=en-US&redirectslug=window.history
Nie jestem pewien, jak dobrze jest obsługiwany przez wiele przeglądarek.
Aktualizacja
Wygląda na to, że to, co nazwałem powyżej, dotyczy tylko przeglądarek typu Gecko.
W przypadku innych przeglądarek spróbuj użyć
history.js
; https://github.com/browserstate/history.jsźródło
Tak więc przepisałem odpowiedź @Bema na TypeScript i tak to wygląda:
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); }
Nie musimy tworzyć właściwości poza
$rootScope
usługą, możemy po prostu zamknąć kod „przy zmianie lokalizacji” i „przy zmianie lokalizacji” naactualLocation
zmiennej lokalnej . Stamtąd możesz robić, co chcesz, tak jak w oryginalnym kodzie. Ze swej strony Pomyślę nadawania zdarzenia tak, że poszczególne kontrolery mogą robić, co im wolno, ale można obejmować działania globalne , jeśli trzeba było .Dziękuję za świetną odpowiedź i mam nadzieję, że pomoże to innym użytkownikom maszynopisu.
źródło
Moim rozwiązaniem tego problemu jest
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(); }); });
źródło
po naciśnięciu przycisku Wstecz kątowy odpala tylko zdarzenie $ routeChangeStart , $ locationChangeStart nie jest wyzwalany.
źródło