Comment puis-je récupérer si l'événement popstate provient d'actions back ou forward avec le pushstate HTML5 ?
-
12-11-2019 - |
Question
Je développe une page Web où, en fonction des actions suivantes ou précédentes, je fais l'animation correspondante, le problème survient lors de l'utilisation du pushstate.Lorsque je reçois l'événement, comment puis-je savoir si l'utilisateur a cliqué sur les boutons d'historique précédent ou suivant à l'aide de l'API Pushstate ?, ou dois-je implémenter quelque chose moi-même ?
La solution
Vous devez le mettre en œuvre vous-même, ce qui est assez simple.
- Lors de l'invocation
pushState
donnez à l'objet de données un identifiant incrémentiel unique (uid). - Quand
onpopstate
le gestionnaire est invoqué ;vérifiez l'uid d'état par rapport à une variable persistante contenant le dernier uid d'état. - Mettez à jour la variable persistante avec l'uid de l'état actuel.
- Effectuez différentes actions selon que l'uid de l'état était supérieur ou inférieur au dernier uid de l'état.
Autres conseils
Cette réponse doit fonctionner avec une application push-État de page, ou une application de plusieurs pages, ou une combinaison des deux.(Corrigé pour corriger le History.length
bug résolu dans le commentaire de Mesqualito.)
Comment ça fonctionne
Nous pouvons facilement écouter les nouvelles entrées dans la pile historique.Nous savons que pour chaque nouvelle entrée, le spécification nécessite que le navigateur :
- "Supprimer toutes les entrées de l'historique de session du contexte de navigation après l'entrée en cours"
- "Ajouter une nouvelle entrée à la fin"
Au moment de l'entrée, donc :
nouvelle position d'entrée = dernière position affichée + 1
La solution est alors :
- Tamponnez chaque entrée de l'historique avec sa propre position dans la pile
- Gardez une trace dans le magasin de session de la dernière position affichée
- Découvrez le sens de déplacement en comparant les deux
Exemple de code
function reorient() // After travelling in the history stack
{
const positionLastShown = Number( // If none, then zero
sessionStorage.getItem( 'positionLastShown' ));
let position = history.state; // Absolute position in stack
if( position === null ) // Meaning a new entry on the stack
{
position = positionLastShown + 1; // Top of stack
// (1) Stamp the entry with its own position in the stack
history.replaceState( position, /*no title*/'' );
}
// (2) Keep track of the last position shown
sessionStorage.setItem( 'positionLastShown', String(position) );
// (3) Discover the direction of travel by comparing the two
const direction = Math.sign( position - positionLastShown );
console.log( 'Travel direction is ' + direction );
// One of backward (-1), reload (0) or forward (1)
}
addEventListener( 'pageshow', reorient );
addEventListener( 'popstate', reorient ); // Travel in same page
Voir aussi un copie en direct du code.
Limitation
Cette solution ignore les entrées historiques des pages externes, étrangères à l'application, comme si l'utilisateur ne les avait jamais visité.Il calcule la direction de voyage uniquement par rapport à la dernière page d'application montrée, quelle que soit la page externe visitée entre les deux.Si vous vous attendez à ce que l'utilisateur pousse les entrées étrangères sur la pile (voir le commentaire d'Atomosk), vous pourriez avoir besoin d'une solution de contournement.