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

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

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

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

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

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

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

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



답변

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

<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를 모두 인라인으로 배치 할 수 있습니다.


답변

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

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는 현재 모든 주요 브라우저에서 지원됩니다.


답변

이 기사에서는 이에 대해 설명합니다. 아래 코드를 참조하십시오.
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>


답변

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

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


답변

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

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

<!-- 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>

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


답변

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


답변

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