programing

window.location일 때 이벤트.href 변경사항

telecom 2023. 10. 17. 20:01
반응형

window.location일 때 이벤트.href 변경사항

나는 어느 시점에서 수정하는 사이트에 대한 그리스몽키 스크립트를 작성하고 있습니다.location.href.

이벤트를 받으려면 어떻게 해야 합니까?window.addEventListener또는 그와 유사한 것)의 경우window.location.href페이지의 변경사항?저는 새로운/수정된 url을 가리키는 문서의 DOM에 대한 접근도 필요합니다.

타임아웃과 여론조사를 포함한 다른 해결책들을 본 적이 있지만, 가능하다면 피하고 싶습니다.

이 스크립트는 내 확장 "Grab Any Media"에서 사용하며 잘 작동합니다(Youtube 사례처럼).

var oldHref = document.location.href;

window.onload = function() {
    var bodyList = document.querySelector("body")

    var observer = new MutationObserver(function(mutations) {
        if (oldHref != document.location.href) {
            oldHref = document.location.href;
            /* Changed ! your code here */
        }
    });
    
    var config = {
        childList: true,
        subtree: true
    };
    
    observer.observe(bodyList, config);
};

최신 자바스크립트 사양으로

const observeUrlChange = () => {
  let oldHref = document.location.href;
  const body = document.querySelector("body");
  const observer = new MutationObserver(mutations => {
    if (oldHref !== document.location.href) {
      oldHref = document.location.href;
      /* Changed ! your code here */
    }
  });
  observer.observe(body, { childList: true, subtree: true });
};

window.onload = observeUrlChange;

OpenAI로 압축됨

window.onload = () => new MutationObserver(mutations => mutations.forEach(() => oldHref !== document.location.href && (oldHref = document.location.href, /* Changed ! your code here */))).observe(document.querySelector("body"), { childList: true, subtree: true });

popstate 이벤트:

popstate 이벤트는 활성 내역 항목이 변경될 때 발생합니다. [...] popstate 이벤트는 뒤로 가기 버튼 클릭(또는 JavaScript에서 history.back() 호출)과 같은 브라우저 작업을 수행할 때만 트리거됩니다.

그래서 듣는 것은.popstate이벤트와 송신.popstate사용시 이벤트history.pushState()에 대해 조치를 취하기에 충분할 것입니다.href변경:

window.addEventListener('popstate', listener);

const pushUrl = (href) => {
  history.pushState({}, '', href);
  window.dispatchEvent(new Event('popstate'));
};

투표를 피할 수는 없습니다, href 교환 이벤트는 없습니다.

어차피 무리하지 않으면 간격을 두는 것은 꽤 가볍습니다.50ms마다 href를 확인하는 것은 성능에 큰 영향을 주지 않습니다.

기본값이 있습니다.onhashchange사용할 수 있는 이벤트.

여기에 문서화됨

다음과 같이 사용할 수 있습니다.

function locationHashChanged( e ) {
    console.log( location.hash );
    console.log( e.oldURL, e.newURL );
    if ( location.hash === "#pageX" ) {
        pageX();
    }
}

window.onhashchange = locationHashChanged;

브라우저가 지원하지 않는 경우oldURL그리고.newURL다음과 같이 바인딩할 수 있습니다.

//let this snippet run before your hashChange event binding code
if( !window.HashChangeEvent )( function() {
    let lastURL = document.URL;
    window.addEventListener( "hashchange", function( event ) {
        Object.defineProperty( event, "oldURL", { enumerable: true, configurable: true, value: lastURL } );
        Object.defineProperty( event, "newURL", { enumerable: true, configurable: true, value: document.URL } );
        lastURL = document.URL;
    } );
} () );

Jquery를 통해서, 그냥 시도해보세요.

$(window).on('beforeunload', function () {
    //your code goes here on location change 
});

javascript를 사용하여:

window.addEventListener("beforeunload", function (event) {
   //your code goes here on location change 
});

문서 참조 : https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload

브라우저를 지원할 때 히스토리 API를 대체하기 위해 현재 구현 중인 새로운 탐색 API를 사용합니다.

navigation.addEventListener('navigate', () => {
  console.log('page changed');
});

이것은 이미 크롬 브라우저에서 작동하지만 파이어폭스와 사파리는 2023년 3월 현재 이 기능을 놓치고 있습니다.

이는 문제를 상당히 단순화하며, 기존 솔루션의 가장 큰 문제점인 단일 페이지 애플리케이션을 염두에 두고 특별히 설계되고 있습니다.더 이상 비싸지 않습니다.MutationObserver화!

언로드 전에 시도해 보셨습니까?이 이벤트는 페이지가 탐색 요청에 응답하기 바로 전에 발생하며, 여기에는 href의 수정이 포함되어야 합니다.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
    <HTML>
    <HEAD>
    <TITLE></TITLE>
    <META NAME="Generator" CONTENT="TextPad 4.6">
    <META NAME="Author" CONTENT="?">
    <META NAME="Keywords" CONTENT="?">
    <META NAME="Description" CONTENT="?">
    </HEAD>

         <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
            <script type="text/javascript">
            $(document).ready(function(){
                $(window).unload(
                        function(event) {
                            alert("navigating");
                        }
                );
                $("#theButton").click(
                    function(event){
                        alert("Starting navigation");
                        window.location.href = "http://www.bbc.co.uk";
                    }
                );

            });
            </script>


    <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">

        <button id="theButton">Click to navigate</button>

        <a href="http://www.google.co.uk"> Google</a>
    </BODY>
    </HTML>

그러나 이는 스크립트 때문이든 누군가가 링크를 클릭하기 때문이든 페이지에서 벗어날 마다 이벤트가 발생합니다.당신의 진짜 과제는 이벤트가 해고되는 여러 가지 이유를 알아내는 것입니다. (만약 이것이 당신의 논리에 중요하다면)

URL이 변경될 때마다 코드를 실행할 수 있는 스크립트(단일 페이지 응용프로그램처럼 페이지 로드 없이):

var previousUrl = '';
var observer = new MutationObserver(function(mutations) {
  if (location.href !== previousUrl) {
      previousUrl = location.href;
      console.log(`URL changed to ${location.href}`);
    }
});

"Leonardo Ciaccio"의 답변을 바탕으로 수정된 코드는 다음과 같습니다. 즉, 루프를 위해 제거된 후 Body Element가 제거되면 재할당됩니다.

window.addEventListener("load", function () {
  let oldHref = document.location.href,
    bodyDOM = document.querySelector("body");
  function checkModifiedBody() {
    let tmp = document.querySelector("body");
    if (tmp != bodyDOM) {
      bodyDOM = tmp;
      observer.observe(bodyDOM, config);
    }
  }
  const observer = new MutationObserver(function (mutations) {
    if (oldHref != document.location.href) {
      oldHref = document.location.href;
      console.log("the location href is changed!");
      window.requestAnimationFrame(checkModifiedBody)
    }
  });
  const config = {
    childList: true,
    subtree: true
  };
  observer.observe(bodyDOM, config);
}, false);

음, 2가지 방법이 있습니다.location.href. 글을 쓸수있거나location.href = "y.html", 페이지를 다시 로드하거나 페이지를 다시 로드하지 않는 히스토리 API를 사용할 수 있습니다.저는 최근에 첫 번째 실험을 많이 했습니다.

자식 창을 열고 부모 창에서 자식 페이지의 로드를 캡처하면 브라우저마다 매우 다르게 동작합니다.유일하게 일반적인 것은 이전 문서를 제거하고 새 문서를 추가한다는 것입니다. 예를 들어, 이전 문서에 준비 상태 변경 또는 이벤트 핸들러 로드를 추가하는 것은 아무런 효과가 없습니다.대부분의 브라우저는 윈도우 객체에서도 이벤트 핸들러를 제거하지만, 유일한 예외는 Firefox입니다.Carma runner를 사용하는 Chrome과 Firefox에서는 readyState 로딩에서 새 문서를 캡처할 수 있습니다.unload + next tick 이벤트 핸들러 이벤트 핸들러를 새할 수 예를 들어 로드 이벤트 핸들러 또는 준비 상태 변경 이벤트 핸들러를 추가하거나 브라우저가 새 URI로 페이지를 로드하고 있음을 기록할 수 있습니다.및된 크롬(GreaseMonkey능)및 오페라라)에서 팬텀텀)JS, IE10, IE11 로딩 상태에서는 새로운 문서를 캡처할 수 없습니다.그 브라우저들에서unload + next tick는 페이지의 로드 이벤트가 발생한 후 수백 밀리초 후에 콜백을 호출합니다.지연 시간은 일반적으로 100~300msec이지만 opera simetime은 다음 틱에 대해 750msec 지연이 발생하여 무섭습니다.따라서 모든 브라우저에서 일관된 결과를 원하는 경우 로드 이벤트 후에 원하는 작업을 수행하지만 그 전에 위치가 무시되지 않는다는 보장은 없습니다.

var uuid = "win." + Math.random();
var timeOrigin = new Date();
var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");


var callBacks = [];
var uglyHax = function (){
    var done = function (){
        uglyHax();
        callBacks.forEach(function (cb){
            cb();
        });
    };
    win.addEventListener("unload", function unloadListener(){
        win.removeEventListener("unload", unloadListener); // Firefox remembers, other browsers don't
        setTimeout(function (){
            // IE10, IE11, Opera, PhantomJS, Chrome has a complete new document at this point
            // Chrome on Karma, Firefox has a loading new document at this point
            win.document.readyState; // IE10 and IE11 sometimes fails if I don't access it twice, idk. how or why
            if (win.document.readyState === "complete")
                done();
            else
                win.addEventListener("load", function (){
                    setTimeout(done, 0);
                });
        }, 0);
    });
};
uglyHax();


callBacks.push(function (){
    console.log("cb", win.location.href, win.document.readyState);
    if (win.location.href !== "http://localhost:4444/y.html")
        win.location.href = "http://localhost:4444/y.html";
    else
        console.log("done");
});
win.location.href = "http://localhost:4444/x.html";

Firefox에서만 스크립트를 실행하는 경우 단순화된 버전을 사용하여 문서를 로드 상태로 캡처할 수 있으므로, 예를 들어 로드된 페이지의 스크립트는 URI 변경 사항을 기록하기 전에 이동할 수 없습니다.

var uuid = "win." + Math.random();
var timeOrigin = new Date();
var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");


var callBacks = [];
win.addEventListener("unload", function unloadListener(){
    setTimeout(function (){
        callBacks.forEach(function (cb){
            cb();
        });
    }, 0);
});


callBacks.push(function (){
    console.log("cb", win.location.href, win.document.readyState);
    // be aware that the page is in loading readyState, 
    // so if you rewrite the location here, the actual page will be never loaded, just the new one
    if (win.location.href !== "http://localhost:4444/y.html")
        win.location.href = "http://localhost:4444/y.html";
    else
        console.log("done");
});
win.location.href = "http://localhost:4444/x.html";

만약 우리가 URI의 해시 부분을 변경하거나 히스토리 API를 사용하는 단일 페이지 응용 프로그램에 대해 말하고 있다면, 당신은 사용할 수 있습니다.hashchange그리고.popstate창문의 사건들을 각각 때까지 할 수 .같은 페이지를 유지할 때까지 역사를 앞뒤로 이동하더라도 캡처할 수 있습니다.문서가 변경되지 않으며 페이지가 실제로 다시 로드되지 않습니다.

ReactJS기타 SPA 애플리케이션은history물건

들어보세요.window.history다음 코드로 업데이트:

function watchHistoryEvents() {
    const { pushState, replaceState } = window.history;

    window.history.pushState = function (...args) {
        pushState.apply(window.history, args);
        window.dispatchEvent(new Event('pushState'));
    };

    window.history.replaceState = function (...args) {
        replaceState.apply(window.history, args);
        window.dispatchEvent(new Event('replaceState'));
    };

    window.addEventListener('popstate', () => console.log('popstate event'));
    window.addEventListener('replaceState', () => console.log('replaceState event'));
    window.addEventListener('pushState', () => console.log('pushState event'));
}
watchHistoryEvents();

또한, 나는 유용한 해결책을 찾았습니다.MutationObserver:

function watchLocation() {
    const observable = () => document.location.pathname;

    let oldValue = observable();
    const observer = new MutationObserver(() => {
        const newValue = observable();

        if (oldValue !== newValue) {
            console.log(`changed: ${oldValue} -> ${newValue}`);
            oldValue = newValue;
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });
}

Mutation Observer API 문서화

언급URL : https://stackoverflow.com/questions/3522090/event-when-window-location-href-changes

반응형