사용자가 뒤로 버튼을 사용하여 페이지로 이동했는지 어떻게 감지합니까?


90

이 질문은 사용자가 브라우저에서 뒤로 버튼을 누를 때 추적 과 유사 합니다. 에서 하지만 동일하지는 않습니다. 해결책이 있으며 여기에 참조 및 피드백을 위해 게시하고 있습니다. 더 나은 옵션이 있다면 나는 모두 귀입니다!

상황은 내가 "in place edit", la flickr가있는 페이지를 가지고 있다는 것입니다. 즉, "설명을 추가하려면 여기를 클릭하십시오"DIV가 있으며, 클릭하면 저장 및 취소 버튼이있는 TEXTAREA로 바뀝니다. 저장을 클릭하면 데이터가 서버에 게시되어 데이터베이스를 업데이트하고 TEXTAREA 대신 DIV에 새 설명이 저장됩니다. 페이지를 새로 고치면 "편집하려면 클릭"옵션과 함께 데이터베이스에서 새 설명이 표시됩니다. 요즘은 상당히 표준적인 웹 2.0 항목입니다.

문제는 다음과 같은 경우입니다.

  1. 페이지가 설명없이로드됩니다.
  2. 사용자가 설명을 추가합니다.
  3. 링크를 클릭하여 페이지를 탐색합니다.
  4. 사용자가 뒤로 버튼을 클릭

그런 다음 표시되는 것은 (브라우저의 캐시에서) 새 설명을 포함하는 동적으로 수정 된 DIV가없는 페이지 버전입니다.

이는 사용자가 업데이트가 손실되었다고 가정하고 변경 사항을 확인하기 위해 페이지를 새로 고쳐야한다는 것을 반드시 이해하지 못할 것이라고 가정하기 때문에 상당히 큰 문제입니다.

따라서 질문은 다음과 같습니다. 페이지가로드 된 후 수정중인 것으로 플래그를 지정하고 사용자가 "다시 이동"할 때이를 감지하고 해당 상황에서 강제로 새로 고침을 수행하는 방법은 무엇입니까?


이것이 당신이 인용 한 질문과 어떻게 다른가요?
innaM

질문은 비슷하지만 환경이 다르기 때문에 대답이 다르기 때문에 틀릴 수 있습니다. 다른 솔루션으로 해결할 수있는 문제에 대한 나의 해석은 사용자가 ajax에 의해로드 된 페이지의 탭을 클릭 한 다음 다른 탭 등을 클릭하는 것입니다. 뒤로 버튼을 클릭하면 이전 탭이 아닌 다른 페이지로 돌아갑니다. 그들은 "페이지 히스토리"내에서 "ajax 히스토리"를 순환하기를 원합니다. 적어도 그것은 야후 브라우저 히스토리 관리자가해야 할 일에 대한 나의 인상입니다. 나는 좀 더 기본적인 것을 추구했습니다.
Tom

허용되는 답변은 iframe 트릭을 특징으로합니다.
innaM

답변:


79

숨겨진 양식을 사용하십시오. 양식 데이터는 다시로드하거나 뒤로 버튼을 눌러 페이지로 돌아갈 때 브라우저에서 (일반적으로) 보존됩니다. 다음 내용이 페이지에 표시됩니다 (아마도 하단 근처).

<form name="ignore_me">
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>

자바 스크립트에서 다음이 필요합니다.

var dirty_bit = document.getElementById('page_is_dirty');
if (dirty_bit.value == '1') window.location.reload();
function mark_page_dirty() {
    dirty_bit.value = '1';
}

양식을 스니핑하는 js는 html이 완전히 파싱 된 후에 실행되어야하지만 사용자 지연이 심각한 문제인 경우 페이지 상단 (js 초)에 양식과 js를 모두 인라인으로 배치 할 수 있습니다.


5
"양식 데이터는 일반적으로 브라우저에 보존됩니다."-확장 할 수 있습니까? 일부 브라우저에서는 보존되지 않습니까? 아니면 어떤 상황에서?

4
사실, 이것이 잘못 될 수 있다고 생각할 수있는 모든 방법을 나열하겠습니다. (1) Opera는 페이지의 전체 상태를 유지하고 js를 다시 실행하지 않습니다. (2) 페이지가 뒤로 버튼으로 서버에서로드되도록 캐시 설정을 조정하면 양식 데이터가 손실 될 수 있습니다. 이는이 질문의 목적에 적합합니다. (3) 전화 브라우저는 훨씬 더 작은 캐시를 가지고 있으며 브라우저는 이미 캐시에서 페이지를 삭제했을 수 있습니다 (이러한 목적에는 문제가되지 않음).
Nick White

10
일부 브라우저에서는 숨겨진 태그가 유지되지 않습니다. 따라서 숨겨진 입력 태그를 사용하는 대신 숨겨진 텍스트 태그를 사용할 수 있습니다. <input type = "text"value = "0"id = '
txt'name

2
이것은 나를 위해 잘 작동했습니다. 나는 그것이 고장날 때 상황이 있다고 확신하지만 모든 해결책은이 문제를 해결할 것입니다.
Joren

Safari 브라우저로 iPhone에서 작동하지 않습니다. 시도해보십시오. 뒤로 버튼을 클릭하면 js가 다시 호출되지 않습니다.
woheras 2015-04-30

53

이 오래된 문제에 대한 매우 쉬운 현대적인 해결책이 있습니다.

if (window.performance && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) {
    alert('Got here using the browser "Back" or "Forward" button.');
}

window.performance는 현재 모든 주요 브라우저에서 지원됩니다.


나는 이것을 들어 본 적이 없다. 방금이 문서 ( developer.mozilla.org/en-US/docs/Web/API/Performance/navigation )를 찾았 으며 자세한 설명을 듣고 싶습니다 (예 : window.performance && window.performance.navigation.type대신 왜 필요 window.performance.navigation.TYPE_BACK_FORWARD합니까?).
라이언

5
window.performance.navigation.TYPE_BACK_FORWARD항상 2와 같은 상수입니다. 그래서 단지 비교를 위해 사용됩니다.
Bassem 2011

Performance.navigation은의 Andorid 및 오페라 미니를 제외한 모든 장치에서 지원하지만, 아무 문제없는 매우 좋은 ( developer.mozilla.org/en-US/docs/Web/API/Performance/navigation )
엘 바즈

1
performance.navigation더 이상 사용되지 않는 것 같습니다. 대신 developer.mozilla.org/en-US/docs/Web/API/…
RubberDuckRabbit

1
Firefox v70은 2뒤로 버튼 히트에 대해 performance.navigation = 을 지원합니다 . v70까지는 1.
Andy Mercer 19

13

이 기사에서는 이에 대해 설명합니다. 아래 코드를 참조하십시오. http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

<html>
    <head>
        <script>

            function pageShown(evt){
                if (evt.persisted) {
                    alert("pageshow event handler called.  The page was just restored from the Page Cache (eg. From the Back button.");
                } else {
                    alert("pageshow event handler called for the initial load.  This is the same as the load event.");
                }
            }

            function pageHidden(evt){
                if (evt.persisted) {
                    alert("pagehide event handler called.  The page was suspended and placed into the Page Cache.");
                } else {
                    alert("pagehide event handler called for page destruction.  This is the same as the unload event.");
                }
            }

            window.addEventListener("pageshow", pageShown, false);
            window.addEventListener("pagehide", pageHidden, false);

        </script>
    </head>
    <body>
        <a href="http://www.webkit.org/">Click for WebKit</a>
    </body>
</html>

1
이것은 좋은 대답이며 최신 Chrome 40 / Firefox 35에서 작동합니다. IE11은 이러한 이벤트를 지원하지 않습니다.
Slava Abakumov

caniuse.com/#feat=page-transition-events 에 따르면 페이지 전환 이벤트는 실제로 IE11 +에서 지원됩니다. 우리가 말한대로이 기능의 전 세계적으로 88 % 범위가 있습니다
Cristian

참고로, Chrome은 뒤로 버튼을 눌러도 event.persisted=를 반환 false합니다. window.performance.navigationChrome 용 또는 PerformanceNavigationTiming을 사용해야합니다 .
Andy Mercer

4

최신 브라우저의 경우 이것이 올바른 방법 인 것 같습니다.

const perfEntries = performance.getEntriesByType('navigation');
if (perfEntries.length && perfEntries[0].type === 'back_forward') {
  console.log('User got here from Back or Forward button.');
}

이것은 2020 년 1 월 현재 "실험적"이지만 잘 지원되는 것 같습니다.

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming


1
== 대신 ===을 사용하는 것이 좋습니다
Aboozar Rajabi

2

위에서 언급했듯이 해결책을 찾았으며 여기에 참조 및 피드백을 위해 게시하고 있습니다.

솔루션의 첫 번째 단계는 페이지에 다음을 추가하는 것입니다.

<!-- at the top of the content page -->
<IFRAME id="page_is_fresh" src="fresh.html" style="display:none;"></IFRAME>
<SCRIPT style="text/javascript">
  function reload_stale_page() { location.reload(); }
</SCRIPT>

의 내용은 fresh.html중요하지 않으므로 다음으로 충분합니다.

<!-- fresh.html -->
<HTML><BODY></BODY></HTML>

클라이언트 측 코드가 페이지를 업데이트 할 때 다음과 같이 수정 사항에 플래그를 지정해야합니다.

function trigger_reload_if_user_clicks_back_button()
{
  // "dis-arm" the reload stale page function so it doesn't fire  
  // until the page is reloaded from the browser's cache
  window.reload_stale_page = function(){};

  // change the IFRAME to point to a page that will reload the 
  // page when it loads
  document.getElementById("page_is_fresh").src = "stale.html";
}

stale.html모든 작업을 수행합니다.로드 reload_stale_page되면 필요한 경우 페이지를 새로 고치는 함수를 호출합니다 . 처음로드 될 때 (즉, 수정 한 후 reload_stale_page함수는 아무 작업도 수행하지 않습니다.)

<!-- stale.html -->
<HTML><BODY>
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT>
</BODY></HTML>

이 단계의 (최소한) 테스트에서 이것은 원하는대로 작동하는 것 같습니다. 내가 간과 한 것이 있습니까?


내가 아는 것은 아니지만 완전히 테스트하지는 않았습니다. getElementById는 일부 이전 브라우저에서 지원되지 않지만 필요한 경우 jquery 또는 다른 것으로 쉽게 교체 할 수 있습니다.
Tom

2

onbeforeunload 이벤트를 사용하여 해결할 수 있습니다 .

window.onbeforeunload = function () { }

onbeforeunload 를 갖는 페이지는 액세스 할 때마다 하나의 시간을 재 구축 할 빈 이벤트 관리 기능을 의미합니다. 자바 스크립트가 다시 실행되고, 서버 측 스크립트가 다시 실행되며, 사용자가 뒤로 또는 앞으로 버튼을 눌러 페이지로 이동 한 경우에도 사용자가 처음으로 페이지를 치는 것처럼 페이지가 빌드됩니다. .

다음은 예제의 전체 코드입니다.

<html>
<head>
<title>onbeforeunload.html</title>
<script>
window.onbeforeunload = function () { }

function myfun()
{
   alert("The page has been refreshed.");
}
</script>

<body onload="myfun()">

Hello World!<br>

</body>
</html>

시도해보고이 페이지를 탐색 한 다음 브라우저의 "뒤로"또는 "앞으로"버튼을 사용하여 돌아 오십시오.

IE, FF 및 Chrome에서 잘 작동합니다.

물론 myfun 함수 내에서 원하는 것은 무엇이든 할 수 있습니다 .

추가 정보 : http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript


나를 위해 Safari에서 작동
Jakob

2

localStorage 또는 sessionStorage ( http://www.w3schools.com/html/html5_webstorage.asp )를 사용하여 숨겨진 양식을 사용하는 대신 플래그를 설정할 수 있습니다 .


내가 사이트를 개설하고 닫을 때 그는이 모든 시간을 감지 할 경우 그것의 좋은 해결 방법하지만 어떻게 당신에게 그것을 할, 내가 열었을 때 바로 감지하고 닫기 전에 다시 갈 필요
엘 바즈

1

이 페이지 사용, 특히 @Nick White의 답변에 대한 @sajith의 의견과이 페이지 : http://www.mrc-productivity.com/techblog/?p=1235

<form name="ignore_me" style="display:none">
    <input type="text" id="reloadValue" name="reloadValue" value="" />
</form>

$(function ()
{
    var date = new Date();
    var time = date.getTime();

    if ($("#reloadValue").val().length === 0)
    {
        $("#reloadValue").val(time);
    }
    else
    {
        $("#reloadValue").val("");
        window.location.reload();
    }
});

1

다음은 jQuery 버전입니다. 사용자가 뒤로 버튼을 눌렀을 때 Safari 데스크톱 / 모바일이 캐시를 처리하는 방식으로 인해 몇 번 사용해야합니다.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        // Loading from cache
    }
});

내가 알 수있는 한 Chrome에서 작동하지 않는 것 같습니다. console.log는 페이지에 액세스하는 방법에 관계없이 else 문 (테스트를 위해 추가됨)에서만 트리거됩니다.
Luke

0

오늘 비슷한 문제가 발생했으며 localStorage (여기에서는 약간의 jQuery로)로 해결했습니다.

$(function() {

    if ($('#page1').length) {
        // this code must only run on page 1

        var checkSteps = function () {
            if (localStorage.getItem('steps') == 'step2') {
                // if we are here, we know that:
                // 1. the user is on page 1
                // 2. he has been on page 2
                // 3. this function is running, which means the user has submitted the form
                // 4. but steps == step2, which is impossible if the user has *just* submitted the form
                // therefore we know that he has come back, probably using the back button of his browser
                alert('oh hey, welcome back!');
            } else {
                setTimeout(checkSteps, 100);
            }
        };

        $('#form').on('submit', function (e) {
            e.preventDefault();
            localStorage.setItem('steps', 'step1'); // if "step1", then we know the user has submitted the form
            checkOrderSteps();
            // ... then do what you need to submit the form and load page 2
        });
    }

    if ($('#page2').length) {
        // this code must only run on page 2
        localStorage.setItem('steps', 'step2');
    }

});

Si 기본적으로 :

1 페이지에서 사용자가 양식을 제출할 때 localStorage에 "steps"값을 설정하여 사용자가 수행 한 단계를 나타냅니다. 동시에이 값이 변경되었는지 확인하는 타임 아웃 기능을 시작합니다 (예 : 초당 10 회).

2 페이지에서 우리는 해당 값을 즉시 변경합니다.

따라서 사용자가 뒤로 버튼을 사용하고 브라우저가 페이지 1을 우리가 떠났을 때의 정확한 상태로 복원하면 checkSteps 함수가 여전히 실행 중이며 localStorage의 값이 변경되었음을 감지 할 수 있습니다 (적절한 조치를 취할 수 있음). ). 이 검사가 목적을 충족하면 계속 실행할 필요가 없으므로 더 이상 setTimeout을 사용하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.