JavaScript에서 URL이 변경되었는지 어떻게 확인합니까? 예를 들어 AJAX를 사용하는 GitHub와 같은 웹 사이트는 # 기호 뒤에 페이지 정보를 추가하여 페이지를 다시로드하지 않고 고유 한 URL을 만듭니다. 이 URL이 변경되는지 감지하는 가장 좋은 방법은 무엇입니까?
- 는 IS
onload
이벤트가 다시 호출? - URL에 대한 이벤트 핸들러가 있습니까?
- 또는 변경 사항을 감지하기 위해 URL을 1 초마다 확인해야합니까?
JavaScript에서 URL이 변경되었는지 어떻게 확인합니까? 예를 들어 AJAX를 사용하는 GitHub와 같은 웹 사이트는 # 기호 뒤에 페이지 정보를 추가하여 페이지를 다시로드하지 않고 고유 한 URL을 만듭니다. 이 URL이 변경되는지 감지하는 가장 좋은 방법은 무엇입니까?
onload
이벤트가 다시 호출?답변:
최신 브라우저 (IE8 +, FF3.6 +, Chrome)에서는에서 hashchange
이벤트를 들을 수 있습니다 window
.
일부 구형 브라우저에서는 계속 확인하는 타이머가 필요합니다 location.hash
. jQuery를 사용하는 경우 정확히 수행 하는 플러그인 이 있습니다.
beforeunload
이벤트 만 표시됩니다 . 코드가 URL 변경을 시작한 경우 가장 잘 알고 있습니다.
locationchange
이벤트 리스너 를 추가하고 싶었습니다 . 아래 수정 후에는 다음과 같이 할 수 있습니다.
window.addEventListener('locationchange', function(){
console.log('location changed!');
})
대조적으로, window.addEventListener('hashchange',()=>{})
URL에서 해시 태그 뒤에있는 부분이 변경되고 window.addEventListener('popstate',()=>{})
항상 작동하지 않는 경우에만 실행됩니다 .
Christian의 답변 과 비슷한이 수정은 기록 개체를 수정하여 일부 기능을 추가합니다.
기본적으로 popstate
이벤트가 있지만 pushstate
및에 대한 이벤트가 없습니다 replacestate
.
이렇게하면이 세 가지 기능이 수정되어 모든 사용자 locationchange
가 사용할 사용자 지정 이벤트 pushstate
와 해당 replacestate
이벤트를 사용하려는 경우 이벤트가 발생합니다.
/* These are the modifications: */
history.pushState = ( f => function pushState(){
var ret = f.apply(this, arguments);
window.dispatchEvent(new Event('pushstate'));
window.dispatchEvent(new Event('locationchange'));
return ret;
})(history.pushState);
history.replaceState = ( f => function replaceState(){
var ret = f.apply(this, arguments);
window.dispatchEvent(new Event('replacestate'));
window.dispatchEvent(new Event('locationchange'));
return ret;
})(history.replaceState);
window.addEventListener('popstate',()=>{
window.dispatchEvent(new Event('locationchange'))
});
이 코드를 사용하십시오
window.onhashchange = function() {
//code
}
jQuery와 함께
$(window).bind('hashchange', function() {
//code
});
약간의 연구 후에 편집하십시오.
어떻게 든 모질라 문서에있는 문서에 바보가 된 것 같습니다. popstate
이벤트 (및 콜백 함수 onpopstate
)하는 트리거되지 때마다 pushState()
또는 replaceState()
코드라고합니다. 따라서 원래 답변은 모든 경우에 적용되지 않습니다.
그러나 @ alpha123에 따라 함수 를 원숭이 패치하여 이를 우회하는 방법이 있습니다 .
var pushState = history.pushState;
history.pushState = function () {
pushState.apply(history, arguments);
fireEvents('pushState', arguments); // Some event-handling function
};
원래 답변
이 질문의 제목이 " URL 변경을 감지하는 방법 "이라는 대답을 감안할 때 해시 앵커뿐만 아니라 전체 경로가 언제 변경되는지 알고 싶은 경우 popstate
이벤트를 수신 할 수 있다는 것입니다 .
window.onpopstate = function(event) {
console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
현재 (2017 년 1 월) 전 세계 브라우저의 92 %에서 popstate 가 지원 됩니다.
jquery (및 플러그인)를 사용하면 할 수 있습니다
$(window).bind('hashchange', function() {
/* things */
});
http://benalman.com/projects/jquery-hashchange-plugin/
그렇지 않으면, setInterval을 사용하고 해시 이벤트 (window.location.hash)의 변경을 확인해야합니다.
최신 정보! 간단한 초안
function hashHandler(){
this.oldHash = window.location.hash;
this.Check;
var that = this;
var detect = function(){
if(that.oldHash!=window.location.hash){
alert("HASH CHANGED - new has" + window.location.hash);
that.oldHash = window.location.hash;
}
};
this.Check = setInterval(function(){ detect() }, 100);
}
var hashDetection = new hashHandler();
window.addEventListener("hashchange", hashChanged);
detect()
기능 을 실행하는 데 너무 바쁘지 않습니까?
해시 변경 이벤트 리스너를 추가하십시오!
window.addEventListener('hashchange', function(e){console.log('hash changed')});
또는 모든 URL 변경 사항을 청취하려면 다음을 수행하십시오.
window.addEventListener('popstate', function(e){console.log('url changed')});
window.onhashchange에는 한 가지만 존재할 수 있으며 다른 사람의 코드를 덮어 쓸 수 있기 때문에 아래 코드와 같은 것이 좋습니다.
// Bad code example
window.onhashchange = function() {
// Code that overwrites whatever was previously in window.onhashchange
}
이 솔루션은 저에게 효과적이었습니다.
var oldURL = "";
var currentURL = window.location.href;
function checkURLchange(currentURL){
if(currentURL != oldURL){
alert("url changed!");
oldURL = currentURL;
}
oldURL = window.location.href;
setInterval(function() {
checkURLchange(window.location.href);
}, 1000);
}
checkURLchange();
setInterval
에 setTimeout
:. "는 checkURLchange () 매 초에 새 통화를 만들 수 있기 때문에, 잠시 후 중단 브라우저를 가져올하여 setInterval ()를 사용에서는 setTimeout () 한 번만 호출되기 때문에 올바른 해결 방법입니다. "
setTimeout
@divibisan이 제안한 것과 같이 대신 setInterval
함수 외부로 이동하십시오 . checkURLchange();
또한 선택 사항이됩니다.
오래된 질문이지만 Location-bar 프로젝트는 매우 유용합니다.
var LocationBar = require("location-bar");
var locationBar = new LocationBar();
// listen to all changes to the location bar
locationBar.onChange(function (path) {
console.log("the current url is", path);
});
// listen to a specific change to location bar
// e.g. Backbone builds on top of this method to implement
// it's simple parametrized Backbone.Router
locationBar.route(/some\-regex/, function () {
// only called when the current url matches the regex
});
locationBar.start({
pushState: true
});
// update the address bar and add a new entry in browsers history
locationBar.update("/some/url?param=123");
// update the address bar but don't add the entry in history
locationBar.update("/some/url", {replace: true});
// update the address bar and call the `change` callback
locationBar.update("/some/url", {trigger: true});
약간의 크롬 확장을 수행하는 동안 추가 문제와 같은 문제에 직면했습니다. 때로는 페이지가 변경되지만 URL은 변경되지 않습니다.
예를 들어 Facebook 홈페이지로 이동하여 '홈'버튼을 클릭하십시오. 페이지를 다시로드하지만 URL은 변경되지 않습니다 (한 페이지 앱 스타일).
99 %의 시간에 Angular, React, Vue 등과 같은 프레임 워크에서 이러한 이벤트를 얻을 수 있도록 웹 사이트를 개발하고 있습니다.
그러나 Chrome 확장 프로그램 (Vanilla JS)의 경우 URL 변경으로 인해 일반적으로 잡힐 수있는 각 "페이지 변경"에 대해 트리거되는 이벤트를 들어야했지만 때로는 그렇지 않습니다.
내 수제 솔루션은 다음과 같습니다.
listen(window.history.length);
var oldLength = -1;
function listen(currentLength) {
if (currentLength != oldLength) {
// Do your stuff here
}
oldLength = window.history.length;
setTimeout(function () {
listen(window.history.length);
}, 1000);
}
따라서 기본적으로 창 기록에 적용되는 leoneckert 솔루션은 단일 페이지 앱에서 페이지가 변경 될 때 변경됩니다.
로켓 과학이 아니라 내가 찾은 가장 깨끗한 솔루션입니다. 여기서 정수 동등성을 확인하고 더 큰 객체 또는 전체 DOM이 아닌 것을 고려하십시오.
window.history
최대 길이는 50입니다 (최소한 Chrome 80 기준). 이 시점 이후에는 window.history.length
항상 50을 리턴합니다.이 경우이 메소드는 변경 사항을 인식하지 못합니다.
jQuery 언로드 기능을보십시오. 모든 것을 처리합니다.
https://api.jquery.com/unload/
언로드 이벤트는 사용자가 페이지를 벗어나 탐색 할 때 창 요소로 전송됩니다. 이것은 많은 것들 중 하나를 의미 할 수 있습니다. 사용자가 링크를 클릭하여 페이지를 떠나거나 주소 표시 줄에 새 URL을 입력했을 수 있습니다. 앞으로 및 뒤로 버튼은 이벤트를 트리거합니다. 브라우저 창을 닫으면 이벤트가 트리거됩니다. 페이지를 다시로드하더라도 먼저 언로드 이벤트가 생성됩니다.
$(window).unload(
function(event) {
alert("navigating");
}
);
아래 답변은 여기에서 (오래된 자바 스크립트 구문 (화살표 기능 없음, IE 10 이상 지원)) : https : //.com/a/52809105/9168962
(function() {
if (typeof window.CustomEvent === "function") return false; // If not IE
function CustomEvent(event, params) {
params = params || {bubbles: false, cancelable: false, detail: null};
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
window.CustomEvent = CustomEvent;
})();
(function() {
history.pushState = function (f) {
return function pushState() {
var ret = f.apply(this, arguments);
window.dispatchEvent(new CustomEvent("pushState"));
window.dispatchEvent(new CustomEvent("locationchange"));
return ret;
};
}(history.pushState);
history.replaceState = function (f) {
return function replaceState() {
var ret = f.apply(this, arguments);
window.dispatchEvent(new CustomEvent("replaceState"));
window.dispatchEvent(new CustomEvent("locationchange"));
return ret;
};
}(history.replaceState);
window.addEventListener("popstate", function() {
window.dispatchEvent(new CustomEvent("locationchange"));
});
})();
setInterval
이전 통화를 취소하지 않고 각 통화에서 새 통화를 시작하고 있습니다.setTimeout