He creado una aplicación web que utiliza los métodos history pushStatey replaceStatepara navegar por las páginas y actualizar el historial.
El guión en sí funciona casi a la perfección; cargará las páginas correctamente y arrojará los errores de la página cuando sea necesario lanzarlos. Sin embargo, he notado un extraño problema en el pushStateque empujará múltiples entradas duplicadas (y reemplazará las entradas anteriores) al historial.
Por ejemplo, digamos que hago lo siguiente (en orden):
Cargue index.php (el historial será: Índice)
Navegue a profile.php (el historial será: Perfil, Índice)
Navegue a search.php (el historial será: Buscar, Buscar, Índice)
Navega hasta dashboard.php
Entonces, finalmente, esto es lo que surgirá en mi historia (en orden de más reciente a más antiguo):
Tablero Tablero
Tablero
Tablero Índice de
búsqueda
El problema con esto es que cuando un usuario hace clic en los botones de avance o retroceso, será redirigido a la página incorrecta o tendrá que hacer clic varias veces para regresar una vez. Eso, y no tendrá sentido si van y revisan su historial.
Esto es lo que tengo hasta ahora:
var Traveller = function(){
this._initialised = false;
this._pageData = null;
this._pageRequest = null;
this._history = [];
this._currentPath = null;
this.abort = function(){
if(this._pageRequest){
this._pageRequest.abort();
}
};
// initialise traveller (call replaceState on load instead of pushState)
return this.init();
};
/*1*/Traveller.prototype.init = function(){
// get full pathname and request the relevant page to load up
this._initialLoadPath = (window.location.pathname + window.location.search);
this.send(this._initialLoadPath);
};
/*2*/Traveller.prototype.send = function(path){
this._currentPath = path.replace(/^\/+|\/+$/g, "");
// abort any running requests to prevent multiple
// pages from being loaded into the DOM
this.abort();
return this._pageRequest = _ajax({
url: path,
dataType: "json",
success: function(response){
// render the page to the dom using the json data returned
// (this part has been skipped in the render method as it
// doesn't involve manipulating the history object at all
window.Traveller.render(response);
}
});
};
/*3*/Traveller.prototype.render = function(data){
this._pageData = data;
this.updateHistory();
};
/*4*/Traveller.prototype.updateHistory = function(){
/* example _pageData would be:
{
"page": {
"title": "This is a title",
"styles": [ "stylea.css", "styleb.css" ],
"scripts": [ "scripta.js", "scriptb.js" ]
}
}
*/
var state = this._pageData;
if(!this._initialised){
window.history.replaceState(state, state.title, "/" + this._currentPath);
this._initialised = true;
} else {
window.history.pushState(state, state.title, "/" + this._currentPath);
}
document.title = state.title;
};
Traveller.prototype.redirect = function(href){
this.send(href);
};
// initialise traveller
window.Traveller = new Traveller();
document.addEventListener("click", function(event){
if(event.target.tagName === "a"){
var link = event.target;
if(link.target !== "_blank" && link.href !== "#"){
event.preventDefault();
// example link would be /profile.php
window.Traveller.redirect(link.href);
}
}
});
Toda la ayuda es apreciada,
salud.
updateHistoryfunción. Ahora, es updateHistoryposible que se te llame dos veces, primero, cuando estás inicializando Traveler ( window.Traveller = new Traveller();, constructor-> init-> send-> render-> updateHistory), y luego también redirectdesde clickeventListener. No lo he probado, solo adivinanzas, así que lo agregué como un comentario y no como una respuesta.