Есть 2 способа изменить файл location.href
. Либо ты можешь написатьlocation.href = "y.html"
, который перезагружает страницу, либо использовать API истории, который не перезагружает страницу. Я недавно много экспериментировал с первым.
Если вы открываете дочернее окно и фиксируете загрузку дочерней страницы из родительского окна, то разные браузеры ведут себя по-разному. Единственное, что является общим: они удаляют старый документ и добавляют новый, поэтому, например, добавление обработчиков событий readystatechange или load к старому документу не имеет никакого эффекта. Большинство браузеров также удаляют обработчики событий из объекта окна, единственным исключением является Firefox. В Chrome с бегуном Karma и в Firefox вы можете захватить новый документ в готовом состоянии загрузки, если вы используетеunload + next tick
. Таким образом, вы можете добавить, например, обработчик событий загрузки или обработчик событий readystatechange или просто зарегистрировать, что браузер загружает страницу с новым URI. В Chrome с ручным тестированием (возможно, GreaseMonkey тоже) и в Opera, PhantomJS, IE10, IE11 вы не можете захватить новый документ в состоянии загрузки. В этих браузерах unload + next tick
обратный вызов вызывается на несколько сотен миллисекунд позже, чем срабатывает событие загрузки страницы. Задержка обычно составляет от 100 до 300 мс, но Opera simetime делает задержку в 750 мс для следующего тика, что пугает. Поэтому, если вы хотите получить согласованный результат во всех браузерах, вы делаете то, что хотите, после события загрузки, но нет гарантии, что местоположение не будет переопределено до этого.
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";
Если вы запускаете свой скрипт только в 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);
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
события окна соответственно. Их можно снимать, даже если вы перемещаетесь по истории назад и вперед, пока не останетесь на той же странице. Документ ими не меняется и страница не перезагружается.