J'ai créé une application Web qui utilise les méthodes history pushStateet replaceStateafin de parcourir les pages tout en mettant à jour l'historique.
Le script lui-même fonctionne presque parfaitement; il chargera les pages correctement et générera des erreurs de page lorsqu'elles doivent être lancées. Cependant, j'ai remarqué un problème étrange où pushStatepoussera plusieurs entrées en double (et remplacera les entrées avant) dans l'historique.
Par exemple, disons que je fais ce qui suit (dans l'ordre):
Charger index.php (l'historique sera: Index)
Accédez à profile.php (l'historique sera: Profile, Index)
Accédez à search.php (l'historique sera: Recherche, Recherche, Index)
Accédez à dashboard.php
Enfin, voici ce qui va ressortir de mon histoire (par ordre du plus récent au plus ancien):
Dashboard
Dashboard
Dashboard
Search
Index
Le problème est que lorsqu'un utilisateur clique sur les boutons avant ou arrière, il sera soit redirigé vers la page incorrecte, soit devra cliquer plusieurs fois pour revenir en arrière une fois. Ça, et ça n'aura aucun sens s'ils vont vérifier leur histoire.
Voici ce que j'ai jusqu'à présent:
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);
}
}
});
Toute aide est appréciée,
Cheers.
updateHistoryfonction. Maintenant, updateHistoryvous pouvez être appelé deux fois, d'abord, lorsque vous initialisez Traveler ( window.Traveller = new Traveller();, constructor-> init-> send-> render-> updateHistory), puis également à redirectpartir de clickeventListener. Je ne l'ai pas testé, juste des devinettes, alors ajoutez-le en tant que commentaire et non en tant que réponse.