사용자가 브라우저의 히스토리 뒤로 버튼을 사용하여 페이지에 들어온 것을 감지 할 수 있습니까? 바람직하게는 angular.js를 사용하여이 작업을 감지하고 싶습니다.
각도 라우팅을 사용하고 싶지 않습니다. 사용자가 양식을 제출하고 서버에 성공적으로 제출하고 리디렉션 한 후 브라우저의 뒤로 버튼을 사용하여 양식으로 돌아가는 경우에도 작동해야합니다.
답변:
다음은 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?');
}
});
});
나는 이것을 시작하기 위해 실행 블록을 사용하고 있습니다. 먼저 실제 위치를 $ rootScope.actualLocation에 저장 한 다음 $ locationChangeSuccess를 수신하고 발생하면 actualLocation을 새 값으로 업데이트합니다.
$ rootScope에서 위치 경로의 변경 사항을 확인하고 새 위치가 previousLocation과 같으면 $ locationChangeSuccess가 실행되지 않았기 때문에 사용자가 기록을 다시 사용했음을 의미합니다.
$locationChangeSuccess
이벤트 발사 후 $watch
콜백. 그러나 뒤로 / 앞으로 버튼 또는 history.back()
API를 사용하여 URL을 변경하면 콜백 전에$locationChangeSuccess
이벤트가 발생 합니다. 따라서 시계 콜백 실행 이 이미 . angular가 내부적으로 작동하는 방식이며이 솔루션은이 내부 동작을 사용합니다. $watch
actualLocation
newLocation
/#/news/?page=2
로 와 같은 URL 쿼리 문자열 변경을 감지하지 않습니다 /#/news/?page=3
. 그것들도 잡으려면 $location.absUrl()
대신 사용할 수 있습니다 $location.path()
(위에서 사용 된 두 곳에서).
보다 정확한 솔루션 (앞뒤로 감지)을 원한다면 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++;
}
}
});
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;
});
원하면 다음과 같이 '$ 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?');
}
});
});
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
서비스에서 속성을 생성 할 필요가 없습니다. 'on location change success'및 'on location changed'코드를 모두 로컬 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();
});
});