브라우저 뒤로 버튼 이벤트를 감지하는 방법-크로스 브라우저

사용자가 브라우저에서 뒤로 버튼을 눌렀는지 여부를 어떻게 정확하게 감지합니까?

#URL시스템을 사용하여 단일 페이지 웹 응용 프로그램에서 인 페이지 뒤로 단추를 어떻게 사용 합니까?

왜 지구상에서 브라우저 백 버튼이 자체 이벤트를 발생시키지 않습니까!?



답변

(참고 : 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);

참조 : 페이지로드시 window.onpopstate


단일 페이지 앱 및 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
  }
}

도움이되는지 알려주세요. 빠진 것이 있으면 기꺼이 이해하겠습니다.


답변

자바 스크립트에서 탐색 유형 2은 브라우저의 뒤로 또는 앞으로 버튼 클릭을 의미하며 브라우저는 실제로 캐시에서 콘텐츠를 가져옵니다.

if(performance.navigation.type == 2)
{
    //Do your code here
}

답변

이것은 확실히 작동합니다 (뒤로 버튼 클릭을 감지하기 위해)

$(window).on('popstate', function(event) {
 alert("pop");
});

답변

이것 좀 봐:

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에서 작동합니다.