답변:
(참고 : Sharky의 피드백에 따라 백 스페이스를 감지하는 코드를 포함 시켰습니다)
그래서 나는 SO에서 이러한 질문을 자주 보았으며 최근에는 뒤로 버튼 기능을 직접 제어하는 문제가 발생했습니다. 내 응용 프로그램 (싱글 페이지가있는 단일 페이지)에 가장 적합한 솔루션을 며칠간 검색 한 후에 뒤로 버튼을 감지하기위한 간단한 브라우저 간 라이브러리가없는 시스템이 나타났습니다.
대부분의 사람들은 다음을 사용하는 것이 좋습니다.
window.onhashchange = function() {
//blah blah blah
}
그러나이 함수는 사용자가 위치 해시를 변경하는 인 페이지 요소를 사용할 때도 호출됩니다. 사용자가 클릭하고 페이지가 앞뒤로 이동할 때 최상의 사용자 환경이 아닙니다.
내 시스템에 대한 일반적인 개요를 제공하기 위해 사용자가 인터페이스를 이동할 때 이전 해시로 배열을 채우고 있습니다. 다음과 같이 보입니다 :
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
꽤 직설적 인. 브라우저 간 지원 및 구형 브라우저 지원을 위해이 작업을 수행합니다. 새 해시를 함수에 전달하면 해시가 저장되어 해시가 변경됩니다 (브라우저 기록에 저장 됨).
또한 lasthash배열을 사용하여 페이지간에 사용자를 이동하는 인 페이지 뒤로 버튼을 사용합니다 . 다음과 같이 보입니다 :
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
따라서 이것은 사용자를 마지막 해시로 다시 이동시키고 배열에서 마지막 해시를 제거합니다 (지금은 앞으로 버튼이 없습니다).
그래서. 사용자가 인 페이지 뒤로 버튼 또는 브라우저 버튼을 사용했는지 여부를 어떻게 감지합니까?
처음에는을 보았지만 window.onbeforeunload아무 소용이 없었습니다. 사용자가 페이지를 변경하려는 경우에만 호출됩니다. 해시 탐색을 사용하는 단일 페이지 응용 프로그램에서는 발생하지 않습니다.
그래서 좀 더 파고 난 후에 플래그 변수를 설정하기위한 권장 사항을 보았습니다. 필자의 경우이 문제는 설정하려고하지만 모든 것이 비동기 적이므로 해시 변경의 if 문에 대해 항상 제 시간에 설정되지는 않는다는 것입니다. .onMouseDown클릭에서 항상 호출 된 것은 아니며 onclick에 추가해도 충분히 빠르게 트리거되지는 않습니다.
나는 사이의 차이를보고 시작했을 때이다 document,하고 window. 마지막 해결책은을 사용하여 플래그를 설정하고을 사용하여 document.onmouseover비활성화하는 것 document.onmouseleave입니다.
사용자의 마우스가 문서 영역 안에있는 동안 (읽기 : 렌더링 된 페이지이지만 브라우저 프레임 제외) 내 부울이로 설정됩니다 true. 마우스가 문서 영역을 벗어나면 부울이로 바뀝니다 false.
이 방법 window.onhashchange으로 다음을 변경할 수 있습니다 .
window.onhashchange = function() {
if (window.innerDocClick) {
window.innerDocClick = false;
} else {
if (window.location.hash != '#undefined') {
goBack();
} else {
history.pushState("", document.title, window.location.pathname);
location.reload();
}
}
}
확인 표시가 나타납니다 #undefined. 내 배열에 사용 가능한 기록이 없으면을 반환하기 때문 undefined입니다. 나는 이것을 사용하여 사용자가 window.onbeforeunload이벤트를 사용하여 떠나기를 원하는지 묻습니다 .
즉, 페이지 내 뒤로 버튼이나 배열을 사용하여 기록을 저장하지 않아도되는 사람들을 위해 :
document.onmouseover = function() {
//User's mouse is inside the page.
window.innerDocClick = true;
}
document.onmouseleave = function() {
//User's mouse has left the page.
window.innerDocClick = false;
}
window.onhashchange = function() {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back button was clicked
}
}
그리고 거기 있습니다. 해시 탐색과 관련하여 뒤로 버튼 사용과 인 페이지 요소를 감지하는 간단한 3 가지 방법입니다.
편집하다:
사용자가 백 스페이스를 사용하여 백 이벤트를 트리거하지 않도록하기 위해 다음을 포함 할 수도 있습니다 ( 이 질문 에 대한 @thetoolman 감사 ).
$(function(){
/*
* this swallows backspace keys on any non-input element.
* stops backspace -> back
*/
var rx = /INPUT|SELECT|TEXTAREA/i;
$(document).bind("keydown keypress", function(e){
if( e.which == 8 ){ // 8 == backspace
if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
e.preventDefault();
}
}
});
});
다음 popstate과 같은 이벤트 핸들러 를 시도 할 수 있습니다 .
window.addEventListener('popstate', function(event) {
// The popstate event is fired each time when the current history entry changes.
var r = confirm("You pressed a Back button! Are you sure?!");
if (r == true) {
// Call Back button programmatically as per user confirmation.
history.back();
// Uncomment below line to redirect to the previous page instead.
// window.location = document.referrer // Note: IE11 is not supporting this.
} else {
// Stay on the current page.
history.pushState(null, null, window.location.pathname);
}
history.pushState(null, null, window.location.pathname);
}, false);
참고 : 최상의 결과를 얻으려면 다른 예기치 않은 문제를 피하기 위해 논리를 구현하려는 특정 페이지에만이 코드를로드해야합니다.
popstate 이벤트는 현재 히스토리 항목이 변경 될 때마다 발생합니다 (사용자가 새 상태로 이동). 즉 브라우저의 뒤로 / 앞으로 버튼이나 경우에 사용자가 클릭 할 때 발생 history.back(), history.forward(), history.go()방법이 프로그래밍 방식이라고합니다.
event.state이벤트 의 is 속성은 기록 상태 개체와 같습니다.
jQuery 구문의 경우 문서를 준비한 후 리스너를 추가하기 위해 감싸십시오.
(function($) {
// Above code here.
})(jQuery);
단일 페이지 앱 및 HTML5 pushState 페이지 의 예제도 참조 하십시오.
<script>
// jQuery
$(window).on('popstate', function (e) {
var state = e.originalEvent.state;
if (state !== null) {
//load content with ajax
}
});
// Vanilla javascript
window.addEventListener('popstate', function (e) {
var state = e.state;
if (state !== null) {
//load content with ajax
}
});
</script>
Chrome 5 이상, Firefox 4 이상, IE 10 이상, Safari 6 이상, Opera 11.5 이상과 호환되어야합니다.
나는이 요구 사항을 꽤 오랫동안 고투하고 있었고 위의 솔루션 중 일부를 구현했습니다. 그러나 나는 관찰을 우연히 발견했으며 Chrome, Firefox 및 Safari 브라우저 + Android 및 iPhone에서 작동하는 것 같습니다.
페이지로드시 :
window.history.pushState({page: 1}, "", "");
window.onpopstate = function(event) {
// "event" object seems to contain value only when the back button is clicked
// and if the pop state event fires due to clicks on a button
// or a link it comes up as "undefined"
if(event){
// Code to handle back button or prevent from navigation
}
else{
// Continue user action through link or button
}
}
도움이되는지 알려주세요. 빠진 것이 있으면 기꺼이 이해하겠습니다.
event앞으로 버튼에도 가치가 있습니다
자바 스크립트에서 탐색 유형 2은 브라우저의 뒤로 또는 앞으로 버튼 클릭을 의미하며 브라우저는 실제로 캐시에서 콘텐츠를 가져옵니다.
if(performance.navigation.type == 2)
{
//Do your code here
}
이것 좀 봐:
history.pushState(null, null, location.href);
window.onpopstate = function () {
history.go(1);
};
잘 작동합니다 ...
if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
alert('hello world');
}
이것은 나를 위해 일한 유일한 솔루션입니다 (onepage 웹 사이트는 아닙니다). Chrome, Firefox 및 Safari에서 작동합니다.
정답은 이미 질문에 대한 답변입니다. 새로운 JavaScript API PerformanceNavigationTiming 을 언급하고 싶습니다 . 더 이상 사용되지 않는 performance.navigation을 대체 합니다 .
사용자가 뒤로 또는 앞으로 버튼을 사용하여 페이지에 방문하면 다음 코드가 콘솔 "back_forward"에 로그인합니다. 프로젝트에서 사용하기 전에 호환성 테이블을 살펴보십시오.
var perfEntries = performance.getEntriesByType("navigation");
for (var i = 0; i < perfEntries.length; i++) {
console.log(perfEntries[i].type);
}
브라우저 : https://jsfiddle.net/Limitlessisa/axt1Lqoz/
모바일 제어 : https://jsfiddle.net/Limitlessisa/axt1Lqoz/show/
$(document).ready(function() {
$('body').on('click touch', '#share', function(e) {
$('.share').fadeIn();
});
});
// geri butonunu yakalama
window.onhashchange = function(e) {
var oldURL = e.oldURL.split('#')[1];
var newURL = e.newURL.split('#')[1];
if (oldURL == 'share') {
$('.share').fadeOut();
e.preventDefault();
return false;
}
//console.log('old:'+oldURL+' new:'+newURL);
}
.share{position:fixed; display:none; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,.8); color:white; padding:20px;
<!DOCTYPE html>
<html>
<head>
<title>Back Button Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body style="text-align:center; padding:0;">
<a href="#share" id="share">Share</a>
<div class="share" style="">
<h1>Test Page</h1>
<p> Back button press please for control.</p>
</div>
</body>
</html>
여기 내가 가져 가라. URL이 변경되었지만 document감지 된 내부에 클릭이 없을 경우 브라우저가 뒤로 (예 또는 앞으로) 있다고 가정합니다. Ajax를 통해 컨텐츠를로드하는 페이지에서이 작업을 수행하려면 2 초 후에 사용자 클릭이 재설정됩니다.
(function(window, $) {
var anyClick, consoleLog, debug, delay;
delay = function(sec, func) {
return setTimeout(func, sec * 1000);
};
debug = true;
anyClick = false;
consoleLog = function(type, message) {
if (debug) {
return console[type](message);
}
};
$(window.document).click(function() {
anyClick = true;
consoleLog("info", "clicked");
return delay(2, function() {
consoleLog("info", "reset click state");
return anyClick = false;
});
});
return window.addEventListener("popstate", function(e) {
if (anyClick !== true) {
consoleLog("info", "Back clicked");
return window.dataLayer.push({
event: 'analyticsEvent',
eventCategory: 'test',
eventAction: 'test'
});
}
});
})(window, jQuery);
이 스레드의 답변 중 일부를 사용하여 IE 및 Chrome / Edge에서 작동하도록 할 수있었습니다. IE11에서는 history.pushState 가 지원되지 않았습니다.
if (history.pushState) {
//Chrome and modern browsers
history.pushState(null, document.title, location.href);
window.addEventListener('popstate', function (event) {
history.pushState(null, document.title, location.href);
});
}
else {
//IE
history.forward();
}
본격적인 구성 요소는 API를 재정의하는 경우에만 구현할 수 있습니다 ( 'history'개체의 메서드 변경) 방금 작성한 클래스를 공유합니다. Chrome 및 Mozilla에서 테스트되었으며 HTML5 및 ECMAScript5-6 만 지원
class HistoryNavigation {
static init()
{
if(HistoryNavigation.is_init===true){
return;
}
HistoryNavigation.is_init=true;
let history_stack=[];
let n=0;
let current_state={timestamp:Date.now()+n};
n++;
let init_HNState;
if(history.state!==null){
current_state=history.state.HNState;
history_stack=history.state.HNState.history_stack;
init_HNState=history.state.HNState;
} else {
init_HNState={timestamp:current_state.timestamp,history_stack};
}
let listenerPushState=function(params){
params=Object.assign({state:null},params);
params.state=params.state!==null?Object.assign({},params.state):{};
let h_state={ timestamp:Date.now()+n};
n++;
let key = history_stack.indexOf(current_state.timestamp);
key=key+1;
history_stack.splice(key);
history_stack.push(h_state.timestamp);
h_state.history_stack=history_stack;
params.state.HNState=h_state;
current_state=h_state;
return params;
};
let listenerReplaceState=function(params){
params=Object.assign({state:null},params);
params.state=params.state!==null?Object.assign({},params.state):null;
let h_state=Object.assign({},current_state);
h_state.history_stack=history_stack;
params.state.HNState=h_state;
return params;
};
let desc=Object.getOwnPropertyDescriptors(History.prototype);
delete desc.constructor;
Object.defineProperties(History.prototype,{
replaceState:Object.assign({},desc.replaceState,{
value:function(state,title,url){
let params={state,title,url};
HistoryNavigation.dispatchEvent('history.state.replace',params);
params=Object.assign({state,title,url},params);
params=listenerReplaceState(params);
desc.replaceState.value.call(this,params.state,params.title,params.url);
}
}),
pushState:Object.assign({},desc.pushState,{
value:function(state,title,url){
let params={state,title,url};
HistoryNavigation.dispatchEvent('history.state.push',params);
params=Object.assign({state,title,url},params);
params=listenerPushState(params);
return desc.pushState.value.call(this, params.state, params.title, params.url);
}
})
});
HistoryNavigation.addEventListener('popstate',function(event){
let HNState;
if(event.state==null){
HNState=init_HNState;
} else {
HNState=event.state.HNState;
}
let key_prev=history_stack.indexOf(current_state.timestamp);
let key_state=history_stack.indexOf(HNState.timestamp);
let delta=key_state-key_prev;
let params={delta,event,state:Object.assign({},event.state)};
delete params.state.HNState;
HNState.history_stack=history_stack;
if(event.state!==null){
event.state.HNState=HNState;
}
current_state=HNState;
HistoryNavigation.dispatchEvent('history.go',params);
});
}
static addEventListener(...arg)
{
window.addEventListener(...arg);
}
static removeEventListener(...arg)
{
window.removeEventListener(...arg);
}
static dispatchEvent(event,params)
{
if(!(event instanceof Event)){
event=new Event(event,{cancelable:true});
}
event.params=params;
window.dispatchEvent(event);
};
}
HistoryNavigation.init();
// exemple
HistoryNavigation.addEventListener('popstate',function(event){
console.log('Will not start because they blocked the work');
});
HistoryNavigation.addEventListener('history.go',function(event){
event.params.event.stopImmediatePropagation();// blocked popstate listeners
console.log(event.params);
// back or forward - see event.params.delta
});
HistoryNavigation.addEventListener('history.state.push',function(event){
console.log(event);
});
HistoryNavigation.addEventListener('history.state.replace',function(event){
console.log(event);
});
history.pushState({h:'hello'},'','');
history.pushState({h:'hello2'},'','');
history.pushState({h:'hello3'},'','');
history.back();
```
document.mouseover는 IE 및 FireFox에서 작동하지 않습니다. 그러나 나는 이것을 시도했다 :
$(document).ready(function () {
setInterval(function () {
var $sample = $("body");
if ($sample.is(":hover")) {
window.innerDocClick = true;
} else {
window.innerDocClick = false;
}
});
});
window.onhashchange = function () {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back or forward button was pressed
}
};
FireFox가 아닌 Chrome 및 IE에서 작동합니다. 여전히 FireFox를 얻기 위해 노력하고 있습니다. JQuery뿐만 아니라 AngularJS 또는 일반 Javascript에서도 브라우저 뒤로 / 앞으로 버튼 클릭을 쉽게 감지 할 수 있습니다.
<input style="display:none" id="__pageLoaded" value=""/>
$(document).ready(function () {
if ($("#__pageLoaded").val() != 1) {
$("#__pageLoaded").val(1);
} else {
shared.isBackLoad = true;
$("#__pageLoaded").val(1);
// Call any function that handles your back event
}
});
위의 코드는 저에게 효과적이었습니다. 모바일 브라우저에서 사용자가 뒤로 버튼을 클릭하면 이전 방문에 따라 페이지 상태를 복원하려고했습니다.
이벤트를 hashchange스 와이프, 클릭 또는 휠로 유발 한 원래 이벤트를 추적 하여 이벤트가 간단한 방문 페이지로 착각하지 않도록 추가 플래그를 사용하여 문제를 해결했습니다. 각각의 이벤트 바인딩. false뒤로 버튼 을 눌렀을 때 브라우저가 플래그를 다시 설정하지 않습니다 .
var evt = null,
canGoBackToThePast = true;
$('#next-slide').on('click touch', function(e) {
evt = e;
canGobackToThePast = false;
// your logic (remember to set the 'canGoBackToThePast' flag back to 'true' at the end of it)
}
위의 옵션을 시도했지만 그중 아무것도 나를 위해 일하지 않습니다. 해결책은 다음과 같습니다.
if(window.event)
{
if(window.event.clientX < 40 && window.event.clientY < 0)
{
alert("Browser back button is clicked...");
}
else
{
alert("Browser refresh button is clicked...");
}
}
이 링크를 참조하십시오 http://www.codeproject.com/Articles/696526/Solution-to-Browser-Back-Button-Click-Event-Handli 자세한 내용을