it-source

AJAX 어플리케이션의 뒤로 버튼 호출 대행 수신

criticalcode 2023. 2. 12. 17:58
반응형

AJAX 어플리케이션의 뒤로 버튼 호출 대행 수신

AJAX 앱이 있어요.사용자가 버튼을 클릭하면 페이지 표시가 바뀝니다.원래 상태로 돌아가기를 기대하며 뒤로 버튼을 클릭하지만 브라우저의 이전 페이지로 이동합니다.

Back 버튼 이벤트를 대행 수신하고 재할당하려면 어떻게 해야 합니까?RSH등의 라이브러리를 조사해 보았습니다만, 해시 태그를 사용하는 것은 어떻게든 도움이 된다고 들었습니다만, 납득할 수 없습니다.

아, 뒤로 버튼.다음과 같이 간단히 취소할 수 있는 JavaScript 이벤트가 "뒤로" 실행된다고 생각할 수 있습니다.

// this does not work
document.onHistoryGo = function() { return false; }

아니요, 그런 일은 없습니다.

만약 당신이 정말로 웹 을 가지고 있다면 (아약스 기능이 있는 웹 사이트가 아니라) 당신이 말한 것처럼 URL에 단편들이 있는 뒤로 버튼을 넘겨받는 것이 합리적입니다.Gmail이 이렇게 해요.웹 앱이 한 페이지에 모두 포함되어 있고, 모든 기능이 내장되어 있는 경우를 말하는 것입니다.

이 방법은 간단합니다.사용자가 수정 작업을 수행할 때마다 이미 접속되어 있는 URL과 동일한 URL로 리다이렉트하지만 다른 해시 조각으로 리다이렉트 할 수 있습니다.예.

window.location.hash = "#deleted_something";
...
window.location.hash = "#did_something_else";

웹 앱의 전체 상태가 해시 가능한 경우 해시를 사용하는 것이 좋습니다.이메일 목록을 가지고 있다고 가정하면, 모든 ID와 읽기/읽기 상태를 연결하고, 이를 fragment 식별자로 사용하여 MD5 해시를 가져올 수 있습니다.

이런 종류의 리다이렉트(해시만 해당)는 서버에서 아무것도 가져오지 않지만 브라우저 기록 목록에 슬롯을 삽입합니다.위의 예에서는 사용자가 "뒤로"를 누르면 주소 표시줄에 #deleted_something이 표시됩니다.그들은 다시 반격했고 그들은 여전히 당신의 페이지에 있지만 해시 없이 있습니다.그리고 다시 돌아오면, 그들은 실제로 그들이 온 곳으로 돌아간다.

다만, JavaScript가 유저가 반격했을 때를 검출하는 것은 어려운 부분입니다(그 때문에, 상태를 되돌릴 수 있습니다).창 위치를 보고 언제 바뀌는지 확인하기만 하면 됩니다.폴링 포함.(나도 알아, 으윽, 여론조사.글쎄요, 지금 크로스 브라우저보다 더 좋은 것은 없습니다.앞으로 갔는지 뒤로 갔는지 알 수 없기 때문에 해시 식별자로 창의력을 발휘해야 합니다.(시퀀스 번호와 연결된 해시일 수도 있습니다...)

이것이 코드의 요지입니다.(jQuery History 플러그인은 이렇게 동작합니다).

var hash = window.location.hash;
setInterval(function(){
    if (window.location.hash != hash) {
        hash = window.location.hash;
        alert("User went back or forward to application state represented by " + hash);
    }
}, 100);

오래된(인기 있는) 질문에 대한 최신 답변을 제공하려면

는 HTML5를 했습니다.history.pushState() ★★★★★★★★★★★★★★★★★」history.replaceState()엔트리를 각각 및 할 수 .은 '어울릴 수 없다'와 할 수 있습니다.window.onpopstate

「」를 사용합니다.history.pushState()합니다.XMLHttpRequest★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★로, 은 URL입니다.thisXMLHttpRequest★★★★★★ 。

출처: Mozilla Developer Network에서 브라우저 이력을 조작합니다.

jQuery를 사용하여 간단한 솔루션을 만들었습니다.

$(window).on('hashchange', function() {
    top.location = '#main';
    // Eventually alert the user describing what happened
});

하지만 지금까지는 구글 크롬에서만 테스트되었습니다.

이것으로 AJAX 기반의 웹 앱도 문제가 해결되었습니다.

이것은 아마도 조금 해킹적이지만 우아한 해킹이라고 할 수 있다.-) 당신이 뒤로 이동하려고 할 때마다 URI에서 해시 부분이 튀어나와 기술적으로 뒤쪽으로 이동하려고 한다.

브라우저 버튼과 마우스 버튼을 모두 클릭하는 것을 차단합니다.또한 1초에 여러 번 클릭해도 되돌릴 수 없습니다.이것은 setTimeout 또는 setInterval을 기반으로 하는 솔루션에서 발생할 수 있는 문제입니다.

darkport의 답변에 대한 설명은 정말 감사하지만, 해시체인지 이벤트를 이용하면 개선할 수 있다고 생각합니다.darkporter가 설명했듯이 모든 버튼이 window.location을 변경하도록 해야 합니다.해시값

  • 가지 은 '우리'를 사용하는 입니다.<button> 「」를 설정하는 .window.location.hash = "#!somehashstring";
  • 하나의 .<a href="#!somehashstring">Button 1</a>이러한 링크를 클릭하면 해시가 자동으로 업데이트됩니다.

해시 기호 뒤에 느낌표가 있는 이유는 구글의 해시방 패러다임을 만족시키기 위해서입니다(자세한 내용은 읽어보세요).검색 엔진으로 인덱스를 작성하려면 편리합니다.해시 문자열은 일반적으로 다음과 같은 이름/값 쌍입니다.#!color=blue&shape=triangle과 같은 목록입니다.#!/blue/triangle웹 것은 이든 상관없습니다.-- 웹 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 。

그런 다음 해시 값이 변경될 때마다(뒤로 버튼을 누를포함) 실행되는 이 코드 비트만 추가하면 됩니다.폴링 루프는 필요 없을 것 같습니다.

window.addEventListener("hashchange", function(){
    console.log("Hash changed to", window.location.hash);
    // .... Do your thing here...
});

Chrome 36 이외에는 테스트해 본 적이 없습니다만, caniuse.com에 의하면, IE8+, FF21+, Chrome21+, 및 Opera Mini를 제외한 대부분의 브라우저에서 사용할 수 있다고 합니다.

아래의 JQuery 코드와 같이 브라우저의 뒤로 버튼을 비활성화하는 것은 매우 쉽습니다.

// History API 
if( window.history && window.history.pushState ){

  history.pushState( "nohb", null, "" );
  $(window).on( "popstate", function(event){
    if( !event.originalEvent.state ){
      history.pushState( "nohb", null, "" );
      return;
    }
  });
}

동작하고 있는 것을 알 수 있습니다.여기 dotnsf와 여기 cssninja가 있습니다.

감사합니다!

는 정상적인 하고 구별되는 을 생각해냈다.back ★★★★★★★★★★★★★★★★★」forward튼 html HTML5 、 API ( IE 9, and 수신하여입니다.이것은 매우 해킹적이지만, 뒤로 및 앞으로 버튼 이벤트를 가로채 원하는 대로 처리하고 싶다면 효과적입니다.이 기능은 리모트 데스크톱창을 띄우고 리모트머신에서 버튼 클릭을 반복할 필요가 있는 경우 등 다양한 시나리오에서 도움이 됩니다.

다음은 뒤로 버튼과 앞으로 버튼의 동작을 덮어씁니다.

var myHistoryOverride = new HistoryButtonOverride(function()
{
    console.log("Back Button Pressed");
    return true;
},
function()
{
    console.log("Forward Button Pressed");
    return true;
});

이러한 콜백 함수 중 하나에서 false가 반환된 경우 브라우저는 일반 백/전송 조작을 수행하고 페이지를 종료합니다.

필요한 스크립트 전체를 다음에 나타냅니다.

function addEvent(el, eventType, handler) {
    if (el.addEventListener) { // DOM Level 2 browsers
       el.addEventListener(eventType, handler, false);
    } else if (el.attachEvent) { // IE <= 8
        el.attachEvent('on' + eventType, handler);
    } else { // ancient browsers
        el['on' + eventType] = handler;
    }
}
function HistoryButtonOverride(BackButtonPressed, ForwardButtonPressed)
{
    var Reset = function ()
    {
        if (history.state == null)
            return;
        if (history.state.customHistoryStage == 1)
            history.forward();
        else if (history.state.customHistoryStage == 3)
            history.back();
    }
    var BuildURLWithHash = function ()
    {
        // The URLs of our 3 history states must have hash strings in them so that back and forward events never cause a page reload.
        return location.origin + location.pathname + location.search + (location.hash && location.hash.length > 1 ? location.hash : "#");
    }
    if (history.state == null)
    {
        // This is the first page load. Inject new history states to help identify back/forward button presses.
        var initialHistoryLength = history.length;
        history.replaceState({ customHistoryStage: 1, initialHistoryLength: initialHistoryLength }, "", BuildURLWithHash());
        history.pushState({ customHistoryStage: 2, initialHistoryLength: initialHistoryLength }, "", BuildURLWithHash());
        history.pushState({ customHistoryStage: 3, initialHistoryLength: initialHistoryLength }, "", BuildURLWithHash());
        history.back();
    }
    else if (history.state.customHistoryStage == 1)
        history.forward();
    else if (history.state.customHistoryStage == 3)
        history.back();

    addEvent(window,"popstate",function ()
    {
        // Called when history navigation occurs.
        if (history.state == null)
            return;
        if (history.state.customHistoryStage == 1)
        {
            if (typeof BackButtonPressed == "function" && BackButtonPressed())
            {
                Reset();
                return;
            }
            if (history.state.initialHistoryLength > 1)
                history.back(); // There is back-history to go to.
            else
                history.forward(); // No back-history to go to, so undo the back operation.
        }
        else if (history.state.customHistoryStage == 3)
        {
            if (typeof ForwardButtonPressed == "function" && ForwardButtonPressed())
            {
                Reset();
                return;
            }
            if (history.length > history.state.initialHistoryLength + 2)
                history.forward(); // There is forward-history to go to.
            else
                history.back(); // No forward-history to go to, so undo the forward operation.
        }
    });
};

이것은 단순한 컨셉으로 동작합니다.페이지가 로드되면 3개의 개별 이력 상태(1, 2, 3)를 생성하여 브라우저를 2번 상태로 이동합니다.상태 2가 중간에 있기 때문에 다음 이력 내비게이션이벤트에서는 상태 1 또는 3 중 하나가 됩니다.이것으로부터, 유저가 누르는 방향을 판별할 수 있습니다.이와 마찬가지로 뒤로 또는 앞으로 버튼 이벤트를 가로챘습니다.그런 다음 원하는 방식으로 처리하고 상태 번호 2로 돌아가 다음 내역 탐색 이벤트를 캡처할 수 있습니다.

HistoryButtonOverride 스크립트를 사용하는 동안에는 history.replaceState 및 history.pushState 메서드를 사용하지 않도록 해야 합니다.그렇지 않으면 이 메서드가 파손됩니다.

프라이버시상의 문제로, 뒤로 버튼을 무효로 하거나 유저의 이력을 조사하는 것은 불가능하지만, 페이지를 변경하지 않고 이 이력에 새로운 엔트리를 작성할 수 있습니다. 프로그램의 상태가마다 AJAX를 합니다.top.location새로운 URI fragment를 사용합니다.

top.location = "#new-application-state";

브라우저 기록 스택에 새 항목이 생성됩니다.많은 AJAX 라이브러리는 Really Simple History와 같은 지루한 세부 정보를 이미 처리하고 있습니다.

저는 이런 걸 해요.이전 앱 상태의 어레이를 유지합니다.

개시처:

var backstack = [];

다음으로 로케이션 해시의 변경을 듣고 변경 시 다음과 같이 합니다.

if (backstack.length > 1 && backstack[backstack.length - 2] == newHash) {
    // Back button was probably pressed
    backstack.pop();
} else
    backstack.push(newHash);

이렇게 하면 사용자 기록을 쉽게 추적할 수 있습니다.(브라우저 보튼이 아닌) 뒤로 버튼을 앱에 구현하려면 다음 작업을 수행합니다.

window.location.hash = backstack.pop();

제 상황에서는 뒤로 버튼을 눌러 사용자가 마지막 페이지로 넘어가는 것을 방지하고 다른 조치를 취하고 싶었습니다.사용방법hashchange나에게 효과가 있는 해결책을 생각해냈다면.이 스크립트는 현재 사용하고 있는 페이지가 이미 해시를 사용하지 않는 것을 전제로 하고 있습니다.

var hashChangedCount = -2;
$(window).on("hashchange", function () {
    hashChangedCount++;
    if (top.location.hash == "#main" && hashChangedCount > 0) {
        console.log("Ah ah ah! You didn't say the magic word!");
    }
    top.location.hash = '#main';
});
top.location.hash = "#";

다른 답변에 대해 제가 안고 있던 문제는hashchange이벤트가 발생하지 않습니다.당신의 상황에 따라, 이것은 당신에게도 효과가 있을 수 있습니다.

브라우저의 뒤로 버튼은 보통 이전 주소로 돌아가려고 합니다.브라우저 javascript에서 네이티브 기기 되돌리기 버튼 누르기 이벤트는 없지만, 위치 및 해시를 사용하여 해킹하여 앱 상태를 변경할 수 있습니다.

다음의 2개의 뷰가 있는 심플한 앱을 상상해 주세요.

  • 가져오기 버튼이 있는 기본 보기
  • 결과 뷰

를 실장하려면 , 다음의 코드 예를 따릅니다.

function goToView (viewName) {
  // before you want to change the view, you have to change window.location.hash.
  // it allows you to go back to the previous view with the back button.
  // so use this function to change your view instead of directly do the job.
  // page parameter is your key to understand what view must be load after this.

  window.location.hash = page
}

function loadView (viewName) {
    // change dom here based on viewName, for example:

    switch (viewName) {
      case 'index':
        document.getElementById('result').style.display = 'none'
        document.getElementById('index').style.display = 'block'
        break
      case 'result':
        document.getElementById('index').style.display = 'none'
        document.getElementById('result').style.display = 'block'
        break
      default:
        document.write('404')
    }
}

window.addEventListener('hashchange', (event) => {
  // oh, the hash is changed! it means we should do our job.
  const viewName = window.location.hash.replace('#', '') || 'index'

  // load that view
  loadView(viewName)
})


// load requested view at start.
if (!window.location.hash) {
  // go to default view if there is no request.
  goToView('index')
} else {
  // load requested view.
  loadView(window.location.hash.replace('#', ''))
}

React 를 사용하는 경우 NPM 모듈 use-history-back-trap 을 사용할 수 있습니다.이것은 커스텀 리액트훅으로, 백 네비게이션을 대행 수신해, 필요에 따라서 나중에 재개할 수 있습니다.또는 필요한 경우 "ApproveNavigation"에서 다른 작업(다른 위치로 이동 등)을 수행합니다.

사용법은 매우 간단합니다.

const SomeFunctionalReactComponent = () => {
   useHistoryBackTrap(approveNavigation)
   // ...
}

여기서 approveNavigation은 백내비게이션을 진행할 때 true(또는 Promise)를 반환하는 함수입니다.

간단한 두 가지 접근법.

Performance.getEntriesBy유형은 "reload", "navigation", "back_forward" 또는 "prender"를 반환하고 다른 유형의 경우 생성할 수 있습니다.

performance.getEntriesByType("navigation").forEach((entry) => {
    console.log(entry.type)
});

쿠키

var HisLen = getCookie("HisLen");
if (HisLen == history.length) {
    console.log("Back or forward or reload button clicked");
}
setTempCookies("HisLen", history.length, 1000 * 3600);

언급URL : https://stackoverflow.com/questions/1844491/intercepting-call-to-the-back-button-in-my-ajax-application

반응형