Ну, є 2 способи змінити location.href
. Або ви можете написати location.href = "y.html"
, що перезавантажує сторінку, або можете використовувати API історії, який не перезавантажує сторінку. Нещодавно я експериментував із першими.
Якщо ви відкриваєте дочірнє вікно і фіксуєте навантаження дочірньої сторінки з батьківського вікна, то різні браузери поводяться дуже по-різному. Єдине загальне, що вони видаляють старий документ і додають новий, тому, наприклад, додавання готового обміну або завантаження обробників подій до старого документа не має ніякого ефекту. Більшість браузерів також видаляють обробники подій з об'єкта вікна, єдиним винятком є Firefox. У Chrome із Karma runner та у Firefox ви можете захопити новий документ у завантажувальний readyState, якщо використовуєтеunload + next tick
. Таким чином, ви можете додати, наприклад, обробник події завантаження або обробник події readystatechange або просто записати, що браузер завантажує сторінку з новим URI. У Chrome із ручним тестуванням (можливо, GreaseMonkey теж) та в Opera, PhantomJS, IE10, IE11 ви не можете захопити новий документ у стані завантаження. У цих браузерах unload + next tick
виклик зворотного виклику відбувається на кілька сотень мсек. Пізніше, ніж запускається подія завантаження сторінки. Затримка, як правило, становить 100-300 мсек, але час опери оперує 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
події вікна. Вони можуть фіксувати, навіть якщо ви рухаєтеся в історії вперед і назад, доки не залишитесь на одній сторінці. Документ цим не змінюється, і сторінка насправді не перезавантажується.