Ho creato un'app Web che utilizza i metodi history pushStatee replaceStateper navigare tra le pagine e allo stesso tempo aggiornare la cronologia.
La sceneggiatura stessa funziona quasi perfettamente; caricherà le pagine correttamente e genererà errori di pagina quando devono essere lanciati. Tuttavia, ho notato uno strano problema in cui pushStatespingerà più voci duplicate (e sostituirà le voci precedenti) nella cronologia.
Ad esempio, supponiamo che io faccia quanto segue (in ordine):
Carica index.php (la cronologia sarà: Indice)
Vai a profile.php (la cronologia sarà: Profilo, Indice)
Vai a search.php (la cronologia sarà: Cerca, Cerca, Indice)
Vai a dashboard.php
Quindi finalmente, questo è ciò che verrà nella mia storia (in ordine dal più recente al più vecchio):
Dashboard
Dashboard Indice di ricerca del
dashboard
Il problema è che quando un utente fa clic sui pulsanti avanti o indietro, verrà reindirizzato alla pagina errata o dovrà fare clic più volte per tornare indietro una volta. Quello, e non ha senso se vanno a controllare la loro storia.
Questo è quello che ho finora:
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);
}
}
});
Tutto l'aiuto è apprezzato,
Saluti.
updateHistoryfunzione. Ora, updateHistorypossono essere sempre chiamato due volte, prima, quando si sta inizializzazione viaggiatore ( window.Traveller = new Traveller();, constructor-> init-> send-> render-> updateHistory), poi anche dal redirectdal clickeventListener. Non l'ho provato, ho solo indovinato, quindi aggiungendolo come commento e non come risposta.