Istnieją 2 sposoby zmiany location.href
. Możesz albo napisać location.href = "y.html"
, który przeładuje stronę, albo możesz użyć API historii, które nie przeładowuje strony. Ostatnio dużo eksperymentowałem z pierwszym.
Jeśli otworzysz okno podrzędne i przechwycisz ładowanie strony podrzędnej z okna nadrzędnego, różne przeglądarki zachowują się bardzo różnie. Jedyne, co jest wspólne, jest to, że usuwają stary dokument i dodają nowy, więc na przykład dodanie programów obsługi zdarzeń readystatechange lub load do starego dokumentu nie daje żadnego efektu. Większość przeglądarek usuwa również programy obsługi zdarzeń z obiektu window, jedynym wyjątkiem jest Firefox. W przeglądarce Chrome z Karma runner i Firefox możesz przechwycić nowy dokument w pliku readyState ładowania, jeśli go używaszunload + next tick
. Możesz więc dodać na przykład procedurę obsługi zdarzeń ładowania lub procedurę obsługi zdarzeń readystatechange lub po prostu zarejestrować, że przeglądarka ładuje stronę z nowym identyfikatorem URI. W przeglądarce Chrome z testowaniem ręcznym (prawdopodobnie również GreaseMonkey) oraz w Operze, PhantomJS, IE10, IE11 nie można przechwycić nowego dokumentu w stanie ładowania. W tych przeglądarkach unload + next tick
wywołuje oddzwanianie kilkaset ms później niż następuje załadowanie strony. Opóźnienie wynosi zwykle 100 do 300 ms, ale opera simetime powoduje 750 ms opóźnienia dla następnego taktu, co jest przerażające. Więc jeśli chcesz uzyskać spójny wynik we wszystkich przeglądarkach, robisz to, co chcesz po zdarzeniu ładowania, ale nie ma gwarancji, że lokalizacja nie zostanie wcześniej zastąpiona.
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);
setTimeout(function (){
win.document.readyState;
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";
Jeśli uruchamiasz swój skrypt tylko w przeglądarce Firefox, możesz użyć uproszczonej wersji i przechwycić dokument w stanie ładowania, więc na przykład skrypt na załadowanej stronie nie może odejść przed zarejestrowaniem zmiany 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);
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";
Jeśli mówimy o aplikacjach jednostronicowych, które zmieniają część hash identyfikatora URI lub używają API historii, możesz użyć hashchange
odpowiednio popstate
zdarzeń i zdarzeń okna. Mogą one przechwytywać, nawet jeśli poruszasz się w historii wstecz i do przodu, dopóki nie pozostaniesz na tej samej stronie. Dokument się nie zmienia, a strona nie jest ponownie ładowana.