Comment modifier l'URL sans recharger la page?

2380

Existe-t-il un moyen de modifier l'URL de la page actuelle sans recharger la page?

J'aimerais accéder à la partie avant le hachage # si possible.

J'ai seulement besoin de changer la partie après le domaine, donc ce n'est pas comme si je violais les politiques inter-domaines.

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads
Le flash
la source
139
Juste pour faciliter la compréhension de la question, voici ce que Facebook fait lorsque vous ouvrez une photo, par exemple. La barre d'URL change pour pointer DIRECTEMENT vers cette photo, afin que vous puissiez partager l'URL sans perdre où vous êtes sur le site. Vous vous souvenez des sites basés sur le cadrage de la dernière décennie? Vous ne pouviez obtenir que l'URL de la page d'accueil, car seuls les cadres internes changeaient. Et c'était terrible.
Spidey
Bien que ce history.pushState()soit probablement la bonne réponse ici, dans cette situation (selon les circonstances exactes ...), la possibilité d'utiliser une redirection côté serveur (comme via l'utilisation de la directive RewriteRule d'Apache) est quelque chose que vous voudrez peut-être envisager, ou du moins Soyez conscient de. Je pensais juste qu'il fallait le mentionner!
Doin

Réponses:

2035

Cela peut maintenant être fait dans Chrome, Safari, Firefox 4+ et Internet Explorer 10pp4 +!

Voir la réponse à cette question pour plus d'informations: Mise à jour de la barre d'adresse avec une nouvelle URL sans hachage ou rechargement de la page

Exemple:

 function processAjaxData(response, urlPath){
     document.getElementById("content").innerHTML = response.html;
     document.title = response.pageTitle;
     window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", urlPath);
 }

Vous pouvez ensuite utiliser window.onpopstatepour détecter la navigation du bouton Précédent / Suivant:

window.onpopstate = function(e){
    if(e.state){
        document.getElementById("content").innerHTML = e.state.html;
        document.title = e.state.pageTitle;
    }
};

Pour un examen plus approfondi de la manipulation de l'historique du navigateur, consultez cet article MDN .

David Murdoch
la source
272
Comment Facebook fait-il alors dans IE7?
Dominic
57
@CHiRiLo vérifier history.js qui fournit une solution de repli pour les navigateurs qui ne prennent pas en charge l'API d'histoire HTML5.
David Murdoch
23
@infensus S'il y a un signe # dans l'URL quelque part, cette astuce existe depuis des années ..
Izkata
34
Que signifie la partie "pp4 +" de "IE10pp4 +"?
Scott Tesler
34
aperçu de la plateforme 4
David Murdoch
590

HTML5 a introduit les méthodes history.pushState()et history.replaceState(), qui vous permettent respectivement d'ajouter et de modifier des entrées d'historique.

window.history.pushState('page2', 'Title', '/page2.php');

En savoir plus ici

Vivart
la source
12
Peut ne pas fonctionner file:///pour des raisons de sécurité, par exemple Firefox 30. Testez localhostavec python -m SimpleHTTPServer.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6
Le premier paramètre devrait être un objet, pas seulement une chaîne.
Alexis Wilke
40
OMI, c'est vraiment la meilleure réponse. Si tout ce que vous voulez faire, c'est mettre à jour l'URL actuelle ({}, null, strNewPath) est tout ce que vous devez faire. Mieux
Craig Jacobs
7
vous pouvez simplement entrer null pour les 2 premiers paramètres si vous ne voulez pas les changer. Vous pouvez également utiliser une URL absolue pour le troisième paramètre.
Andrew
3
Ce serait bien si vous mettiez plus d'informations dans la réponse. Je n'ai aucune idée de ce que fait le paramètre 1.
RedClover
130

Vous pouvez également utiliser HTML5 replaceState si vous souhaitez modifier l'URL mais ne souhaitez pas ajouter l'entrée à l'historique du navigateur:

if (window.history.replaceState) {
   //prevents browser from storing history with each change:
   window.history.replaceState(statedata, title, url);
}

Cela «casserait» la fonctionnalité du bouton de retour. Cela peut être nécessaire dans certains cas, comme une galerie d'images (où vous souhaitez que le bouton de retour revienne à la page d'index de la galerie au lieu de revenir en arrière dans chaque image que vous avez consultée) tout en donnant à chaque image sa propre URL unique.

George Filippakos
la source
110

Voici ma solution (newUrl est votre nouvelle URL que vous souhaitez remplacer par l'actuelle):

history.pushState({}, null, newUrl);
Haimei
la source
1
Mieux vaut tester d'abord avec if (history.pushState) {} Juste au cas où l'ancien navigateur.
Craig Jacobs
Cela ne fonctionne plus que vous obtiendrez dans Firefox: l'opération n'est pas sécurisée.
kkatusic
Et l'utilisateur peut même définir un signet avec cette approche, magnifique! Je peux maintenant mettre à jour l'URL sur l'entrée utilisateur et il peut directement mettre en signet quels que soient ses paramètres.
codepleb
107

REMARQUE: Si vous travaillez avec un navigateur HTML5, vous devez ignorer cette réponse. Cela est désormais possible, comme le montrent les autres réponses.

Il n'y a aucun moyen de modifier l' URL dans le navigateur sans recharger la page. L'URL représente la dernière page chargée. Si vous le changez ( document.location), il rechargera la page.

Une raison évidente est que vous écrivez un site www.mysite.comqui ressemble à une page de connexion bancaire. Ensuite, vous modifiez la barre d'URL du navigateur pour dire www.mybank.com. L'utilisateur ne saura absolument pas qu'il regarde vraiment www.mysite.com.

Robin Day
la source
33
Je ne veux pas changer le domaine, seulement le chemin et le nom du fichier.
TheFlash
5
Cela n'empêche toujours pas les risques de sécurité potentiels car le navigateur n'a aucune idée que le domaine / mysite et le domaine / othersite sont tous deux considérés comme "sûrs" par l'utilisateur. Peut-être que la question devrait être: pourquoi voulez-vous changer l'URL? Pour le masquer à l'utilisateur, vous pouvez simplement exécuter votre application dans un iframe.
Robin Day
5
Vous pouvez réellement le faire avec Flash. Il vous permettra de modifier l'URL sans faire de demande. Cela est possible car Flash fonctionne en dehors du navigateur, mais très étroitement avec lui.
Nick Berardi
142
Je dois dire qu'il existe des raisons parfaitement valables de vouloir modifier l'URL dans la barre d'adresse côté client. Par exemple, si vous avez une table de données avec pagination, tri et filtrage, et que vous voulez que ces éléments soient alimentés par Ajax, mais mettez toujours à jour l'URL afin que l'état actuel de la page puisse être mis en signet. Je peux comprendre les risques de sécurité liés à la modification du nom de domaine (hameçonnage, etc.), mais pourquoi les navigateurs ne permettent-ils pas que la partie de l'URL à droite du domaine de premier niveau soit modifiable via un script?
Dimanche Ironfoot
41
cette réponse n'est plus vraie à 100%. Voir ma réponse pour plus de détails.
David Murdoch
83
parent.location.hash = "hello";
Martin.
la source
15
Je veux changer l'URL, pas seulement le hachage - #mydata
TheFlash
42
Changer le hachage peut être utile dans ajax car c'est une sorte d'état sans utiliser de cookies, est signable et compatible avec les boutons de retour du navigateur. Gmail l'utilise de nos jours pour le rendre plus convivial.
Matthew Lock
@Jarvis: quelle est la différence?
bruyant
Le suivi côté serveur @noisy ne peut pas voir les hachages sauf s'il est envoyé explicitement au service de suivi.
RedYetiCo
ce n'est pas utile si vous utilisez un framework mvc qui route sur le hachage, par exemple backbone.
catbadger
27

Dans les navigateurs modernes et HTML5 , il existe une méthode appelée pushStatesur fenêtre history. Cela va changer l'URL et la pousser dans l'historique sans charger la page.

Vous pouvez l'utiliser comme ceci, cela prendra 3 paramètres, 1) l'état de l'objet 2) le titre et une URL):

window.history.pushState({page: "another"}, "another page", "example.html");

Cela changera l'URL, mais ne rechargera pas la page. De plus, il ne vérifie pas si la page existe, donc si vous faites du code JavaScript qui réagit à l'URL, vous pouvez travailler avec eux comme ceci.

Il y a aussi history.replaceState()qui fait exactement la même chose, sauf qu'il modifiera l'historique actuel au lieu d'en créer un nouveau!

Vous pouvez également créer une fonction pour vérifier si elle history.pushStateexiste, puis continuer avec le reste comme ceci:

function goTo(page, title, url) {
  if ("undefined" !== typeof history.pushState) {
    history.pushState({page: page}, title, url);
  } else {
    window.location.assign(url);
  }
}

goTo("another page", "example", 'example.html');

Vous pouvez également modifier le #for <HTML5 browsers, qui ne rechargera pas la page. C'est la façon dont Angular utilise pour faire du SPA selon le hashtag ...

Changer #est assez facile, faire comme:

window.location.hash = "example";

Et vous pouvez le détecter comme ceci:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}
Alireza
la source
Serait window.onhashchangeet window.onpopstateferait la même chose dans ce cas?
J0ANMM
Comment charger également le contenu d'une page? Il remplace simplement l'URL
MD. Atiqur Rahman
Chargez le contenu comme vous le feriez normalement avec ajax.
AndroidDev
26

Le HTML5 replaceState est la réponse, comme déjà mentionné par Vivart et geo1701. Cependant, il n'est pas pris en charge dans tous les navigateurs / versions. History.js encapsule les fonctionnalités d'état HTML5 et fournit une prise en charge supplémentaire pour les navigateurs HTML4.

Thomas Stjernegaard Jeppesen
la source
24

Avant HTML5, nous pouvons utiliser:

parent.location.hash = "hello";

et:

window.location.replace("http:www.example.com");

Cette méthode rechargera votre page, mais HTML5 a introduit le history.pushState(page, caption, replace_url)qui ne devrait pas recharger votre page.

Éclat
la source
2
Le problème avec history.pushState(..), c'est que si vous souhaitez rediriger vers un autre domaine, la stratégie interdomaine entre en vigueur. Tandis qu'avec la window.location.replace(..)redirection vers un autre domaine est possible.
OSWorX
23

Si ce que vous essayez de faire est de permettre aux utilisateurs de mettre en signet / partager des pages, et que vous n'avez pas besoin que ce soit exactement la bonne URL, et que vous n'utilisez pas d'ancrage de hachage pour autre chose, alors vous pouvez le faire en deux les pièces; vous utilisez le fichier location.hash décrit ci-dessus, puis implémentez une vérification sur la page d'accueil, pour rechercher une URL contenant une ancre de hachage et vous rediriger vers le résultat suivant.

Par exemple:

1) L'utilisateur est activé www.site.com/section/page/4

2) L'utilisateur fait une action qui change l'URL en www.site.com/#/section/page/6(avec le hachage). Supposons que vous ayez chargé le contenu correct de la page 6 dans la page, donc à part le hachage, l'utilisateur n'est pas trop dérangé.

3) L'utilisateur transmet cette URL à quelqu'un d'autre ou la met en signet

4) Quelqu'un d'autre, ou le même utilisateur à une date ultérieure, va à www.site.com/#/section/page/6

5) Le code sur www.site.com/redirige l'utilisateur vers www.site.com/section/page/6, en utilisant quelque chose comme ceci:

if (window.location.hash.length > 0){ 
   window.location = window.location.hash.substring(1);
}

J'espère que cela a du sens! C'est une approche utile pour certaines situations.

Jeremy Warne
la source
17

Vous trouverez ci-dessous la fonction pour modifier l'URL sans recharger la page. Il n'est pris en charge que pour HTML5.

  function ChangeUrl(page, url) {
        if (typeof (history.pushState) != "undefined") {
            var obj = {Page: page, Url: url};
            history.pushState(obj, obj.Page, obj.Url);
        } else {
            window.location.href = "homePage";
            // alert("Browser does not support HTML5.");
        }
    }

  ChangeUrl('Page1', 'homePage');
Suraj
la source
2
@Green, page est un titre abrégé pour l'état vers lequel vous vous déplacez. Firefox ignore actuellement ce paramètre, bien qu'il puisse l'utiliser à l'avenir. Passer la chaîne vide ici devrait être à l'abri des modifications futures de la méthode. De: developer.mozilla.org/en-US/docs/Web/API/…
Snook
13

Toute modification de la loction (ou window.locationou document.location) provoquera une demande sur cette nouvelle URL, si vous ne modifiez pas seulement le fragment d'URL. Si vous changez l'URL, vous changez l'URL.

Utilisez des techniques de réécriture d'URL côté serveur comme mod_rewrite d'Apache si vous n'aimez pas les URL que vous utilisez actuellement.

Gombo
la source
Puis-je utiliser "location.pathname" ??
TheFlash
3
Non, la modification de cet attribut entraînera également une demande.
Gumbo
11

Vous pouvez ajouter des balises d'ancrage. Je l'utilise sur mon site afin de pouvoir suivre avec Google Analytics ce que les gens visitent sur la page.

Je viens d'ajouter une balise d'ancrage, puis la partie de la page que je veux suivre:

var trackCode = "/#" + urlencode($("myDiv").text());
window.location.href = "http://www.piano-chords.net" + trackCode;
pageTracker._trackPageview(trackCode);
Nate
la source
9

Comme l'a souligné Thomas Stjernegaard Jeppesen, vous pouvez utiliser History.js pour modifier les paramètres d'URL pendant que l'utilisateur navigue à travers vos liens et applications Ajax.

Près d'une année s'est écoulée depuis cette réponse, et History.js a grandi et est devenu plus stable et multi-navigateur. Maintenant, il peut être utilisé pour gérer les états d'historique dans les navigateurs compatibles HTML5 ainsi que dans de nombreux navigateurs HTML4 uniquement. Dans cette démo, vous pouvez voir un exemple de son fonctionnement (ainsi que la possibilité d'essayer ses fonctionnalités et ses limites.

Si vous avez besoin d'aide pour utiliser et implémenter cette bibliothèque, je vous suggère de jeter un œil au code source de la page de démonstration: vous verrez que c'est très facile à faire.

Enfin, pour une explication complète de ce que peuvent être les problèmes liés à l'utilisation des hachages (et des hashbangs), consultez ce lien de Benjamin Lupton.

Erenor Paz
la source
8

Utiliser à history.pushState()partir de l'API HTML 5 History.

Reportez-vous à l' API HTML5 History pour plus de détails.

Prathamesh Rasam
la source
7

Vous pouvez utiliser cette fonction belle et simple pour ainsi ainsi n'importe où sur votre application.

function changeurl(url, title) {
    var new_url = '/' + url;
    window.history.pushState('data', 'Title', new_url);
    document.title = title;
}

Vous pouvez non seulement modifier l'URL, mais vous pouvez également mettre à jour le titre.

Tout le monde est très utile.

Dheeraj Thedijje
la source
1
Fonctionne comme un charme même pour les ancreswindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD