Normalisation du routage côté client grâce à une toute nouvelle API qui remanie complètement la création d'applications monopages.
Les applications monopages (SPA) sont définies par une fonctionnalité de base : elles réécrivent dynamiquement leur contenu à mesure que l'utilisateur interagit avec le site, au lieu de la méthode par défaut qui consiste à charger des pages entièrement nouvelles à partir du serveur.
Bien que les SPA aient pu vous apporter cette fonctionnalité via l'API History (ou, dans certains cas, en ajustant la partie #hash du site), il s'agit d'une API maladroite développée bien avant que les SPA ne deviennent la norme. Le Web a besoin d'une approche complètement nouvelle. L'API Navigation est une API proposée qui remanie complètement cet espace, au lieu d'essayer de simplement corriger les aspérités de l'API History. (Par exemple, Scroll Restoration a corrigé l'API History au lieu d'essayer de la réinventer.)
Cet article décrit l'API Navigation dans les grandes lignes. Pour lire la proposition technique, consultez le brouillon de rapport dans le dépôt WICG.
Exemple d'utilisation
Pour utiliser l'API Navigation, commencez par ajouter un écouteur "navigate" sur l'objet navigation global.
Cet événement est fondamentalement centralisé : il se déclenche pour tous les types de navigation, que l'utilisateur ait effectué une action (cliquer sur un lien, envoyer un formulaire, revenir en arrière ou en avant, par exemple) ou que la navigation ait été déclenchée de manière programmatique (c'est-à-dire via le code de votre site).
Dans la plupart des cas, il permet à votre code de remplacer le comportement par défaut du navigateur pour cette action.
Pour les SPA, cela signifie probablement que l'utilisateur reste sur la même page et que le contenu du site est chargé ou modifié.
Un NavigateEvent est transmis à l'écouteur "navigate", qui contient des informations sur la navigation, telles que l'URL de destination, et vous permet de répondre à la navigation de manière centralisée.
Voici un exemple d'écouteur "navigate" de base :
navigation.addEventListener('navigate', navigateEvent => {
// Exit early if this navigation shouldn't be intercepted.
// The properties to look at are discussed later in the article.
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname === '/') {
navigateEvent.intercept({handler: loadIndexPage});
} else if (url.pathname === '/cats/') {
navigateEvent.intercept({handler: loadCatsPage});
}
});
Vous pouvez gérer la navigation de deux manières :
- Appelez
intercept({ handler })(comme décrit ci-dessus) pour gérer la navigation. - Appelez
preventDefault(), qui peut annuler complètement la navigation.
Cet exemple appelle intercept() sur l'événement.
Le navigateur appelle votre rappel handler, qui doit configurer le prochain état de votre site.
Un objet de transition, navigation.transition, est alors créé. D'autres codes peuvent l'utiliser pour suivre la progression de la navigation.
Les deux méthodes, intercept() et preventDefault(), sont généralement autorisées, mais il existe des cas où elles ne peuvent pas être appelées.
Vous ne pouvez pas gérer les navigations via intercept() si la navigation est une navigation cross-origin.
De plus, vous ne pouvez pas annuler une navigation via preventDefault() si l'utilisateur appuie sur les boutons "Retour" ou "Suivant" de son navigateur. Vous ne devez pas pouvoir piéger vos utilisateurs sur votre site.
(Cette question est en cours de discussion sur GitHub.)
Même si vous ne pouvez pas arrêter ni intercepter la navigation elle-même, l'événement "navigate" se déclenchera quand même.
Il est informatif. Par exemple, votre code peut enregistrer un événement Analytics pour indiquer qu'un utilisateur quitte votre site.
Pourquoi ajouter un autre événement à la plate-forme ?
Un écouteur d'événements "navigate" centralise la gestion des modifications d'URL dans une SPA.
Il s'agit d'une proposition difficile à mettre en œuvre avec les anciennes API.
Si vous avez déjà écrit le routage de votre propre SPA à l'aide de l'API History, vous avez peut-être ajouté un code comme celui-ci :
function updatePage(event) {
event.preventDefault(); // we're handling this link
window.history.pushState(null, '', event.target.href);
// TODO: set up page based on new URL
}
const links = [...document.querySelectorAll('a[href]')];
links.forEach(link => link.addEventListener('click', updatePage));
Cette liste est correcte, mais non exhaustive. Les liens peuvent apparaître et disparaître sur votre page, et ce ne sont pas les seuls moyens pour les utilisateurs de naviguer sur les pages. Par exemple, ils peuvent envoyer un formulaire ou même utiliser une carte image. Votre page peut traiter ces cas, mais il existe une longue liste de possibilités qui pourraient être simplifiées, ce que permet la nouvelle API Navigation.
De plus, ce qui précède ne gère pas la navigation vers l'arrière ni vers l'avant. Il existe un autre événement pour cela, "popstate".
Personnellement, l'API History me semble pouvoir aider à résoudre ces problèmes.
Toutefois, il ne comporte que deux zones de surface : répondre si l'utilisateur appuie sur "Retour" ou "Suivant" dans son navigateur, et envoyer et remplacer des URL. Il n'a pas d'analogie avec "navigate", sauf si vous configurez manuellement des écouteurs pour les événements de clic, par exemple, comme indiqué ci-dessus.
Choisir comment gérer une navigation
navigateEvent contient de nombreuses informations sur la navigation que vous pouvez utiliser pour décider comment gérer une navigation particulière.
Voici les principales propriétés :
canIntercept- Si la valeur est "false", vous ne pouvez pas intercepter la navigation. Les navigations cross-origin et les traversées cross-document ne peuvent pas être interceptées.
destination.url- Il s'agit probablement de l'information la plus importante à prendre en compte lors de la gestion de la navigation.
hashChange- "True" si la navigation s'effectue dans le même document et que le hachage est la seule partie de l'URL qui diffère de l'URL actuelle.
Dans les SPA modernes, le hachage doit servir à créer des liens vers différentes parties du document actuel. Par conséquent, si
hashChangeest défini sur "true", vous n'avez probablement pas besoin d'intercepter cette navigation. downloadRequest- Si la valeur est "true", la navigation a été lancée par un lien avec un attribut
download. Dans la plupart des cas, vous n'avez pas besoin de l'intercepter. formData- Si cette valeur n'est pas nulle, cette navigation fait partie d'un envoi de formulaire POST.
Veillez à en tenir compte lorsque vous gérez la navigation.
Si vous ne souhaitez gérer que les navigations GET, évitez d'intercepter les navigations où
formDatan'est pas nul. Consultez l'exemple de gestion des envois de formulaires plus loin dans cet article. navigationType- correspond à
"reload","push","replace"ou"traverse". Si la valeur est"traverse", cette navigation ne peut pas être annulée viapreventDefault().
Par exemple, la fonction shouldNotIntercept utilisée dans le premier exemple pourrait ressembler à ceci :
function shouldNotIntercept(navigationEvent) {
return (
!navigationEvent.canIntercept ||
// If this is just a hashChange,
// just let the browser handle scrolling to the content.
navigationEvent.hashChange ||
// If this is a download,
// let the browser perform the download.
navigationEvent.downloadRequest ||
// If this is a form submission,
// let that go to the server.
navigationEvent.formData
);
}
Interception
Lorsque votre code appelle intercept({ handler }) à partir de son écouteur "navigate", il informe le navigateur qu'il prépare maintenant la page pour le nouvel état mis à jour et que la navigation peut prendre un certain temps.
Le navigateur commence par capturer la position de défilement de l'état actuel, afin qu'elle puisse être éventuellement restaurée ultérieurement, puis il appelle votre rappel handler.
Si votre handler renvoie une promesse (ce qui se produit automatiquement avec les fonctions asynchrones), cette promesse indique au navigateur la durée de la navigation et si elle a réussi.
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
},
});
}
});
Par conséquent, cette API introduit un concept sémantique que le navigateur comprend : une navigation SPA est en cours, au fil du temps, et modifie le document d'une URL et d'un état précédents vers une nouvelle URL et un nouvel état. Cela présente plusieurs avantages potentiels, y compris en termes d'accessibilité : les navigateurs peuvent afficher le début, la fin ou l'échec potentiel d'une navigation. Chrome, par exemple, active son indicateur de chargement natif et permet à l'utilisateur d'interagir avec le bouton "Arrêter". (Cela ne se produit pas actuellement lorsque l'utilisateur navigue à l'aide des boutons "Retour" et "Suivant", mais ce problème sera bientôt résolu.)
Validation de la navigation
Lors de l'interception des navigations, la nouvelle URL prendra effet juste avant l'appel de votre rappel handler.
Si vous ne mettez pas à jour le DOM immédiatement, l'ancien contenu s'affiche pendant un certain temps avec la nouvelle URL.
Cela a une incidence sur des éléments tels que la résolution des URL relatives lors de la récupération de données ou du chargement de nouvelles sous-ressources.
Une méthode permettant de retarder le changement d'URL est discutée sur GitHub, mais il est généralement recommandé de mettre à jour immédiatement la page avec une sorte d'espace réservé pour le contenu à venir :
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
// The URL has already changed, so quickly show a placeholder.
renderArticlePagePlaceholder();
// Then fetch the real data.
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
},
});
}
});
Cela permet non seulement d'éviter les problèmes de résolution d'URL, mais aussi de donner l'impression de rapidité, car vous répondez instantanément à l'utilisateur.
Signaux d'abandon
Étant donné que vous pouvez effectuer des tâches asynchrones dans un gestionnaire intercept(), la navigation peut devenir redondante.
Cela se produit dans les cas suivants :
- L'utilisateur clique sur un autre lien ou un code effectue une autre navigation. Dans ce cas, l'ancienne navigation est abandonnée au profit de la nouvelle.
- L'utilisateur clique sur le bouton "Arrêter" du navigateur.
Pour faire face à l'une de ces possibilités, l'événement transmis à l'écouteur "navigate" contient une propriété signal, qui est une AbortSignal.
Pour en savoir plus, consultez Abortable fetch.
En bref, il fournit un objet qui déclenche un événement lorsque vous devez arrêter votre travail.
Vous pouvez notamment transmettre un AbortSignal à tous les appels que vous effectuez vers fetch(), ce qui annulera les requêtes réseau en cours si la navigation est interrompue.
Cela permet à la fois d'économiser la bande passante de l'utilisateur et de rejeter le Promise renvoyé par fetch(), ce qui empêche tout code suivant d'effectuer des actions telles que la mise à jour du DOM pour afficher une navigation sur une page désormais non valide.
Voici l'exemple précédent, mais avec getArticleContent intégré, montrant comment AbortSignal peut être utilisé avec fetch() :
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
// The URL has already changed, so quickly show a placeholder.
renderArticlePagePlaceholder();
// Then fetch the real data.
const articleContentURL = new URL(
'/get-article-content',
location.href
);
articleContentURL.searchParams.set('path', url.pathname);
const response = await fetch(articleContentURL, {
signal: navigateEvent.signal,
});
const articleContent = await response.json();
renderArticlePage(articleContent);
},
});
}
});
Gestion du défilement
Lorsque vous intercept() une navigation, le navigateur tente de gérer le défilement automatiquement.
Pour les navigations vers une nouvelle entrée d'historique (lorsque navigationEvent.navigationType est "push" ou "replace"), cela signifie tenter de faire défiler la page jusqu'à la partie indiquée par le fragment d'URL (la partie après le #) ou réinitialiser le défilement en haut de la page.
Pour les rechargements et les traversées, cela signifie restaurer la position de défilement à l'endroit où cette entrée d'historique a été affichée pour la dernière fois.
Par défaut, cela se produit une fois que la promesse renvoyée par votre handler est résolue. Toutefois, si vous souhaitez faire défiler l'écran plus tôt, vous pouvez appeler navigateEvent.scroll() :
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
navigateEvent.scroll();
const secondaryContent = await getSecondaryContent(url.pathname);
addSecondaryContent(secondaryContent);
},
});
}
});
Vous pouvez également désactiver complètement la gestion automatique du défilement en définissant l'option scroll de intercept() sur "manual" :
navigateEvent.intercept({
scroll: 'manual',
async handler() {
// …
},
});
Gestion de la sélection
Une fois la promesse renvoyée par votre handler résolue, le navigateur sélectionne le premier élément dont l'attribut autofocus est défini, ou l'élément <body> si aucun élément ne possède cet attribut.
Vous pouvez désactiver ce comportement en définissant l'option focusReset de intercept() sur "manual" :
navigateEvent.intercept({
focusReset: 'manual',
async handler() {
// …
},
});
Événements de réussite et d'échec
Lorsque votre gestionnaire intercept() est appelé, deux cas de figure peuvent se présenter :
- Si la
Promiserenvoyée est remplie (ou si vous n'avez pas appeléintercept()), l'API Navigation déclenche"navigatesuccess"avec unEvent. - Si le
Promiserenvoyé est refusé, l'API déclenche"navigateerror"avec unErrorEvent.
Ces événements permettent à votre code de gérer la réussite ou l'échec de manière centralisée. Par exemple, vous pouvez gérer la réussite en masquant un indicateur de progression précédemment affiché, comme ceci :
navigation.addEventListener('navigatesuccess', event => {
loadingIndicator.hidden = true;
});
Vous pouvez également afficher un message d'erreur en cas d'échec :
navigation.addEventListener('navigateerror', event => {
loadingIndicator.hidden = true; // also hide indicator
showMessage(`Failed to load page: ${event.message}`);
});
L'écouteur d'événements "navigateerror", qui reçoit un ErrorEvent, est particulièrement pratique, car il est garanti de recevoir toutes les erreurs du code qui configure une nouvelle page.
Vous pouvez simplement await fetch() en sachant que si le réseau n'est pas disponible, l'erreur sera finalement routée vers "navigateerror".
Entrées de navigation
navigation.currentEntry permet d'accéder à l'entrée actuelle.
Il s'agit d'un objet qui décrit l'emplacement actuel de l'utilisateur.
Cette entrée inclut l'URL actuelle, les métadonnées permettant d'identifier cette entrée au fil du temps et l'état fourni par le développeur.
Les métadonnées incluent key, une propriété de chaîne unique de chaque entrée qui représente l'entrée actuelle et son emplacement.
Cette clé reste la même même si l'URL ou l'état de l'entrée actuelle changent.
Il se trouve toujours au même emplacement.
À l'inverse, si un utilisateur appuie sur "Retour" et rouvre ensuite la même page, key changera, car cette nouvelle entrée crée un nouvel emplacement.
Pour un développeur, key est utile, car l'API Navigation vous permet de rediriger directement l'utilisateur vers une entrée avec une clé correspondante.
Vous pouvez le conserver, même dans les états d'autres entrées, afin de passer facilement d'une page à l'autre.
// On JS startup, get the key of the first loaded page
// so the user can always go back there.
const {key} = navigation.currentEntry;
backToHomeButton.onclick = () => navigation.traverseTo(key);
// Navigate away, but the button will always work.
await navigation.navigate('/another_url').finished;
État
L'API Navigation expose une notion d'état, qui correspond à des informations fournies par le développeur et stockées de manière persistante dans l'entrée d'historique actuelle, mais qui ne sont pas directement visibles par l'utilisateur.
Cette méthode est très semblable à history.state dans l'API History, mais elle a été améliorée.
Dans l'API Navigation, vous pouvez appeler la méthode .getState() de l'entrée actuelle (ou de n'importe quelle entrée) pour renvoyer une copie de son état :
console.log(navigation.currentEntry.getState());
Par défaut, il s'agit de undefined.
État du paramètre
Bien que les objets d'état puissent être modifiés, ces modifications ne sont pas enregistrées dans l'entrée d'historique. Par conséquent :
const state = navigation.currentEntry.getState();
console.log(state.count); // 1
state.count++;
console.log(state.count); // 2
// But:
console.info(navigation.currentEntry.getState().count); // will still be 1
La bonne façon de définir l'état est pendant la navigation dans le script :
navigation.navigate(url, {state: newState});
// Or:
navigation.reload({state: newState});
Où newState peut être n'importe quel objet clonable.
Si vous souhaitez mettre à jour l'état de l'entrée actuelle, il est préférable d'effectuer une navigation qui remplace l'entrée actuelle :
navigation.navigate(location.href, {state: newState, history: 'replace'});
Votre écouteur d'événements "navigate" peut ensuite détecter ce changement via navigateEvent.destination :
navigation.addEventListener('navigate', navigateEvent => {
console.log(navigateEvent.destination.getState());
});
Mettre à jour l'état de manière synchrone
En général, il est préférable de mettre à jour l'état de manière asynchrone via navigation.reload({state: newState}), puis votre écouteur "navigate" peut appliquer cet état. Toutefois, il arrive que le changement d'état soit déjà entièrement appliqué au moment où votre code en est informé, par exemple lorsque l'utilisateur active ou désactive un élément <details> ou modifie l'état d'une entrée de formulaire. Dans ce cas, vous pouvez mettre à jour l'état afin que ces modifications soient conservées lors des rechargements et des traversées. Pour ce faire, vous pouvez utiliser updateCurrentEntry() :
navigation.updateCurrentEntry({state: newState});
Un événement est également prévu pour vous présenter ce changement :
navigation.addEventListener('currententrychange', () => {
console.log(navigation.currentEntry.getState());
});
Toutefois, si vous réagissez aux changements d'état dans "currententrychange", vous risquez de diviser, voire de dupliquer, votre code de gestion d'état entre l'événement "navigate" et l'événement "currententrychange", alors que navigation.reload({state: newState}) vous permettrait de le gérer en un seul endroit.
État vs paramètres d'URL
Comme l'état peut être un objet structuré, il est tentant de l'utiliser pour l'ensemble de l'état de votre application. Toutefois, dans de nombreux cas, il est préférable de stocker cet état dans l'URL.
Si vous souhaitez que l'état soit conservé lorsque l'utilisateur partage l'URL avec un autre utilisateur, stockez-le dans l'URL. Sinon, l'objet d'état est la meilleure option.
Accéder à toutes les entrées
Toutefois, l'entrée actuelle ne fait pas tout.
L'API permet également d'accéder à la liste complète des entrées parcourues par un utilisateur sur votre site grâce à son appel navigation.entries(), qui renvoie un tableau d'instantanés d'entrées.
Cela peut être utilisé, par exemple, pour afficher une interface utilisateur différente en fonction de la façon dont l'utilisateur a accédé à une page spécifique, ou simplement pour revenir aux URL précédentes ou à leurs états.
Cela est impossible avec l'API History actuelle.
Vous pouvez également écouter un événement "dispose" sur des NavigationHistoryEntry individuels, qui est déclenché lorsque l'entrée ne fait plus partie de l'historique du navigateur. Cela peut se produire lors d'un nettoyage général, mais aussi lors de la navigation. Par exemple, si vous revenez en arrière de 10 pages, puis que vous avancez, ces 10 entrées d'historique seront supprimées.
Exemples
L'événement "navigate" se déclenche pour tous les types de navigation, comme indiqué ci-dessus.
(Il existe en fait une longue annexe dans la spécification de tous les types possibles.)
Pour de nombreux sites, le cas le plus courant est celui où l'utilisateur clique sur un <a href="...">. Toutefois, il existe deux types de navigation plus complexes qui méritent d'être abordés.
Navigation programmatique
La première est la navigation programmatique, où la navigation est provoquée par un appel de méthode dans votre code côté client.
Vous pouvez appeler navigation.navigate('/another_page') depuis n'importe quel endroit de votre code pour déclencher une navigation.
Cette opération sera gérée par l'écouteur d'événements centralisé enregistré sur l'écouteur "navigate", et votre écouteur centralisé sera appelé de manière synchrone.
Il s'agit d'une agrégation améliorée des anciennes méthodes telles que location.assign() et d'autres, ainsi que des méthodes pushState() et replaceState() de l'API History.
La méthode navigation.navigate() renvoie un objet contenant deux instances Promise dans { committed, finished }.
Cela permet à l'invocateur d'attendre que la transition soit "validée" (l'URL visible a changé et un nouveau NavigationHistoryEntry est disponible) ou "terminée" (toutes les promesses renvoyées par intercept({ handler }) sont terminées ou rejetées, en raison d'un échec ou d'une préemption par une autre navigation).
La méthode navigate possède également un objet d'options, dans lequel vous pouvez définir les éléments suivants :
state: état de la nouvelle entrée d'historique, tel qu'il est disponible via la méthode.getState()surNavigationHistoryEntry.history: peut être défini sur"replace"pour remplacer l'entrée d'historique actuelle.info: objet à transmettre à l'événement de navigation vianavigateEvent.info.
info peut être utile, par exemple, pour désigner une animation particulière qui fait apparaître la page suivante.
(L'autre option consiste à définir une variable globale ou à l'inclure dans le #hash. Les deux options sont un peu maladroites.)
Il est à noter que ce info ne sera pas rejoué si un utilisateur provoque une navigation ultérieure, par exemple à l'aide des boutons "Précédent" et "Suivant".
En fait, la valeur sera toujours undefined dans ces cas.
navigation dispose également d'un certain nombre d'autres méthodes de navigation, qui renvoient toutes un objet contenant { committed, finished }.
J'ai déjà mentionné traverseTo() (qui accepte un key désignant une entrée spécifique dans l'historique de l'utilisateur) et navigate().
Il inclut également back(), forward() et reload().
Ces méthodes sont toutes gérées, tout comme navigate(), par l'écouteur d'événements "navigate" centralisé.
Envois de formulaires
Deuxièmement, l'envoi HTML <form> via POST est un type spécial de navigation que l'API Navigation peut intercepter.
Bien qu'il inclue une charge utile supplémentaire, la navigation est toujours gérée de manière centralisée par l'écouteur "navigate".
Vous pouvez détecter l'envoi d'un formulaire en recherchant la propriété formData sur NavigateEvent.
Voici un exemple qui transforme simplement tout envoi de formulaire en un envoi qui reste sur la page actuelle via fetch() :
navigation.addEventListener('navigate', navigateEvent => {
if (navigateEvent.formData && navigateEvent.canIntercept) {
// User submitted a POST form to a same-domain URL
// (If canIntercept is false, the event is just informative:
// you can't intercept this request, although you could
// likely still call .preventDefault() to stop it completely).
navigateEvent.intercept({
// Since we don't update the DOM in this navigation,
// don't allow focus or scrolling to reset:
focusReset: 'manual',
scroll: 'manual',
handler() {
await fetch(navigateEvent.destination.url, {
method: 'POST',
body: navigateEvent.formData,
});
// You could navigate again with {history: 'replace'} to change the URL here,
// which might indicate "done"
},
});
}
});
Qu'est-ce qui manque ?
Malgré la nature centralisée du gestionnaire d'événements "navigate", la spécification actuelle de l'API Navigation ne déclenche pas "navigate" lors du premier chargement d'une page.
Pour les sites qui utilisent le rendu côté serveur (SSR) pour tous les états, cela peut être acceptable. Votre serveur peut renvoyer l'état initial correct, ce qui est le moyen le plus rapide de fournir du contenu à vos utilisateurs.
Toutefois, les sites qui utilisent du code côté client pour créer leurs pages devront peut-être créer une fonction supplémentaire pour initialiser leur page.
Un autre choix de conception intentionnel de l'API Navigation est qu'elle ne fonctionne que dans un seul frame, c'est-à-dire la page de premier niveau ou un seul <iframe> spécifique.
Cela a plusieurs implications intéressantes qui sont détaillées dans la spécification, mais qui, en pratique, réduiront la confusion des développeurs.
L'ancienne API History présente un certain nombre de cas extrêmes déroutants, comme la prise en charge des frames. La nouvelle API Navigation gère ces cas extrêmes dès le départ.
Enfin, il n'existe pas encore de consensus sur la modification ou la réorganisation programmatiques de la liste des entrées parcourues par l'utilisateur. Cette question est actuellement en discussion, mais une option pourrait être d'autoriser uniquement les suppressions : soit les entrées historiques, soit "toutes les entrées futures". Cette dernière option permettrait un état temporaire. Par exemple, en tant que développeur, je pourrais :
- poser une question à l'utilisateur en accédant à une nouvelle URL ou à un nouvel état ;
- permettre à l'utilisateur de terminer son travail (ou de revenir en arrière)
- supprimer une entrée de l'historique une fois une tâche terminée ;
Cela peut être parfait pour les modaux ou les interstitiels temporaires : la nouvelle URL est une URL que l'utilisateur peut quitter à l'aide du geste "Retour", mais il ne peut pas revenir en avant par erreur pour l'ouvrir à nouveau (car l'entrée a été supprimée). Cela n'est tout simplement pas possible avec l'API History actuelle.
Essayer l'API Navigation
L'API Navigation est disponible dans Chrome 102 sans flags. Vous pouvez également tester une démo de Domenic Denicola.
Bien que l'ancienne API History semble simple, elle n'est pas très bien définie et présente un grand nombre de problèmes concernant les cas extrêmes et la façon dont elle a été implémentée différemment dans les navigateurs. Nous espérons que vous nous ferez part de vos commentaires sur la nouvelle API Navigation.
Références
- WICG/navigation-api
- Position de Mozilla sur les normes
- Intent To Prototype
- Examen du TAG
- Entrée Chromestatus
Remerciements
Merci à Thomas Steiner, Domenic Denicola et Nate Chapin d'avoir relu cet article.