¿Cómo modifico la URL sin volver a cargar la página?

2378

¿Hay alguna manera de modificar la URL de la página actual sin volver a cargar la página?

Me gustaría acceder a la porción antes del # hash si es posible.

Solo necesito cambiar la porción después del dominio, por lo que no es que esté violando las políticas entre dominios.

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads
El flash
fuente
139
Solo para facilitar la comprensión de la pregunta, esto es lo que hace Facebook cuando abres una foto, por ejemplo. La barra de URL cambia para apuntar DIRECTAMENTE a esa foto, para que pueda compartir la URL sin perder su ubicación en el sitio. ¿Recuerdas los sitios basados ​​en la elaboración de la última década? Solo podía obtener la URL de la página de inicio, porque solo los marcos internos estaban cambiando. Y eso fue terrible.
Spidey
Si bien history.pushState()es probablemente la respuesta correcta aquí, en esta situación (dependiendo de las circunstancias exactas ...) la posibilidad de usar una redirección del lado del servidor (como mediante el uso de la directiva RewriteRule de Apache) es algo que quizás desee considerar, o al menos ser consciente de. ¡Solo pensé que debería mencionarse!
Doin

Respuestas:

2033

¡Esto ahora se puede hacer en Chrome, Safari, Firefox 4+ e Internet Explorer 10pp4 +!

Consulte la respuesta de esta pregunta para obtener más información: Actualización de la barra de direcciones con nueva URL sin hash o recarga de la página

Ejemplo:

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

Luego puede usar window.onpopstatepara detectar el botón de navegación hacia atrás / adelante:

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

Para obtener una visión más detallada sobre la manipulación del historial del navegador, consulte este artículo de MDN .

David Murdoch
fuente
272
¿Cómo lo hace Facebook en IE7 entonces?
Dominic
57
@CHiRiLo echa un vistazo a history.js, que proporciona una alternativa para los navegadores que no admiten la API de historial HTML5.
David Murdoch
23
@infensus Si hay un signo # en la URL en alguna parte, ese truco ha existido durante años ...
Izkata
34
¿Qué significa la parte "pp4 +" de "IE10pp4 +"?
Scott Tesler
34
vista previa de la plataforma 4
David Murdoch
588

HTML5 introdujo los métodos history.pushState()y history.replaceState(), que le permiten agregar y modificar entradas del historial, respectivamente.

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

Lea más sobre esto desde aquí

Vivart
fuente
12
Puede no funcionar file:///por razones de seguridad, por ejemplo, Firefox 30. Pruebe localhostcon python -m SimpleHTTPServer.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
66
Se espera que el primer parámetro sea un objeto, no solo una cadena.
Alexis Wilke
40
OMI, esta es realmente la mejor respuesta. Si todo lo que quiere hacer es actualizar la URL actual ({}, null, strNewPath) es todo lo que necesita hacer. Lo mejor es probar primero con if (history.pushState) {}
Craig Jacobs
77
puede ingresar nulo para los primeros 2 parámetros si no desea cambiarlos. También puede usar una url absoluta para el tercer parámetro.
Andrew
3
Sería bueno si pones más información solo EN la respuesta. No tengo idea de lo que hace el parámetro 1.
RedClover
130

También puede usar HTML5 replaceState si desea cambiar la URL pero no desea agregar la entrada al historial del navegador:

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

Esto 'rompería' la funcionalidad del botón de retroceso. Esto puede ser necesario en algunos casos, como una galería de imágenes (donde desea que el botón Atrás regrese a la página de índice de la galería en lugar de retroceder a través de todas y cada una de las imágenes que vio) mientras le da a cada imagen su propia URL única.

George Filippakos
fuente
110

Aquí está mi solución (newUrl es su nueva URL que desea reemplazar con la actual):

history.pushState({}, null, newUrl);
Haimei
fuente
1
Lo mejor es probar primero con if (history.pushState) {} Por si acaso el navegador anterior.
Craig Jacobs
Esto ya no funcionará en Firefox: la operación es insegura.
kkatusic
Y el usuario puede incluso establecer un marcador con ese enfoque, ¡hermoso! Ahora puedo actualizar la url en la entrada del usuario y él puede marcar directamente cualesquiera que sean sus configuraciones.
codepleb
107

NOTA: Si está trabajando con un navegador HTML5, debe ignorar esta respuesta. Esto ahora es posible como se puede ver en las otras respuestas.

No hay forma de modificar la URL en el navegador sin volver a cargar la página. La URL representa la última página cargada. Si lo cambias (document.location ), volverá a cargar la página.

Una razón obvia es que usted escribe un sitio www.mysite.comque parece una página de inicio de sesión bancaria. Luego cambia la barra de URL del navegador para decir www.mybank.com. El usuario ignorará totalmente lo que realmente está mirando www.mysite.com.

Día de robin
fuente
33
No quiero cambiar el dominio, solo la ruta y el nombre del archivo.
TheFlash
55
Esto todavía no detiene los riesgos potenciales de seguridad ya que el navegador no tiene idea de que el usuario considera que el dominio / mysite y el dominio / othersite son "seguros". Quizás la pregunta debería ser ¿por qué quieres cambiar la URL? Si es para ocultarlo al usuario, simplemente puede ejecutar su aplicación dentro de un iframe.
Robin Day
55
Realmente puedes hacer esto con Flash. Le permitirá modificar la URL sin hacer una solicitud. Esto es posible porque Flash funciona fuera del navegador, pero muy estrechamente con él.
Nick Berardi
142
Tengo que decir que hay razones perfectamente válidas para querer modificar la URL en la barra de direcciones del lado del cliente. Por ejemplo, si tiene una tabla de datos con paginación, clasificación y filtrado, y desea que esas cosas funcionen con Ajax, pero aún así actualiza la URL para que el estado actual de la página sea marcado. Puedo entender los riesgos de seguridad al modificar el nombre de dominio (phishing, etc.), pero ¿por qué los navegadores no permiten que solo la parte de la URL a la derecha del dominio de nivel superior se pueda modificar mediante un script?
Domingo Ironfoot
41
Esta respuesta ya no es 100% verdadera. Vea mi respuesta para más detalles.
David Murdoch
83
parent.location.hash = "hello";
Martín.
fuente
15
Quiero cambiar la URL, no solo el hash - #mydata
TheFlash
42
Cambiar el hash puede ser útil en ajax, ya que es una especie de estado sin usar cookies, se puede marcar como favorito y es compatible con los botones de retroceso del navegador. Gmail usa esto hoy en día para hacerlo más amigable con el navegador.
Matthew Lock
@Jarvis: ¿cuál es la diferencia?
ruidoso
@noisy El seguimiento del lado del servidor no puede ver los hashes a menos que se envíen explícitamente al servicio de seguimiento.
RedYetiCo
esto no es útil si está utilizando un marco de trabajo de mvc que enruta en hash, por ejemplo, backbone.
catbadger 01 de
27

En los navegadores modernos y HTML5 , hay un método llamado pushStateen la ventanahistory . Eso cambiará la URL y la enviará al historial sin cargar la página.

Puede usarlo así, tomará 3 parámetros, 1) objeto de estado 2) título y una URL):

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

Esto cambiará la URL, pero no volverá a cargar la página. Además, no comprueba si la página existe, por lo que si hace algún código JavaScript que reacciona a la URL, puede trabajar con ellos de esta manera.

También hay history.replaceState() quien hace exactamente lo mismo, excepto que modificará el historial actual en lugar de crear uno nuevo!

También puede crear una función para verificar si history.pushStateexiste, luego continuar con el resto de esta manera:

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');

También puede cambiar el #for <HTML5 browsers, que no volverá a cargar la página. Así es como Angular usa para hacer SPA según el hashtag ...

Cambiar #es bastante fácil, haciendo como:

window.location.hash = "example";

Y puedes detectarlo así:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}
Alireza
fuente
¿Haría window.onhashchangey window.onpopstateharía lo mismo en este caso?
J0ANMM
¿Cómo cargar el contenido de la página también? Simplemente reemplaza la URL
MD. Atiqur Rahman
Cargue contenido como lo haría normalmente con ajax.
AndroidDev
26

El HTML5 replaceState es la respuesta, como ya lo mencionaron Vivart y geo1701. Sin embargo, no es compatible con todos los navegadores / versiones. History.js incluye características de estado HTML5 y proporciona soporte adicional para navegadores HTML4.

Thomas Stjernegaard Jeppesen
fuente
24

Antes de HTML5 podemos usar:

parent.location.hash = "hello";

y:

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

Este método volverá a cargar su página, pero HTML5 introdujo el history.pushState(page, caption, replace_url) que no debería volver a cargar su página.

Brillar
fuente
2
El problema history.pushState(..)es que si desea redirigir a otro dominio, la política de dominio cruzado entrará en vigencia. Mientras que con la window.location.replace(..)redirección a otro dominio es posible.
OSWorX
23

Si lo que intenta hacer es permitir que los usuarios marquen / compartan páginas, y no necesita que sea exactamente la URL correcta, y no está utilizando anclas hash para nada más, puede hacerlo en dos partes; usa el archivo location.hash mencionado anteriormente y luego implementa una verificación en la página de inicio para buscar una URL con un ancla de hash y redirigirlo al resultado posterior.

Por ejemplo:

1) El usuario está encendido www.site.com/section/page/4

2) El usuario realiza alguna acción que cambia la URL a www.site.com/#/section/page/6 (con el hash). Supongamos que ha cargado el contenido correcto para la página 6 en la página, por lo que, aparte del hash, el usuario no se molesta demasiado.

3) El usuario pasa esta URL a otra persona o la marca como favorita

4) Alguien más, o el mismo usuario en una fecha posterior, va a www.site.com/#/section/page/6

5) El código en www.site.com/redirige al usuario www.site.com/section/page/6, usando algo como esto:

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

Espero que tenga sentido! Es un enfoque útil para algunas situaciones.

Jeremy Warne
fuente
17

A continuación se muestra la función para cambiar la URL sin volver a cargar la página. Solo es compatible con 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
fuente
2
@Green, la página es un título corto para el estado al que te estás mudando. Firefox actualmente ignora este parámetro, aunque puede usarlo en el futuro. Pasar la cadena vacía aquí debería estar a salvo de futuros cambios en el método. De: developer.mozilla.org/en-US/docs/Web/API/…
Snook
13

Cualquier cambio en la ubicación (ya sea window.locationo document.location) causará una solicitud en esa nueva URL, si no solo está cambiando el fragmento de URL. Si cambia la URL, cambia la URL.

Utilice técnicas de reescritura de URL del lado del servidor como mod_rewrite de Apache si no le gustan las URL que está utilizando actualmente.

Gumbo
fuente
¿Puedo usar "location.pathname"?
TheFlash
3
No, cambiar ese atributo también provocará una solicitud.
Gumbo
11

Puede agregar etiquetas de anclaje. Lo uso en mi sitio para poder rastrear con Google Analytics lo que la gente visita en la página.

Solo agrego una etiqueta de anclaje y luego la parte de la página que quiero rastrear:

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

Como señaló Thomas Stjernegaard Jeppesen, podría usar History.js para modificar los parámetros de URL mientras el usuario navega a través de sus enlaces y aplicaciones Ajax.

Ha pasado casi un año desde esa respuesta, y History.js creció y se volvió más estable y de navegador cruzado. Ahora se puede usar para administrar estados de historial en HTML5 compatible, así como en muchos navegadores solo HTML4. En esta demostración , puede ver un ejemplo de cómo funciona (además de poder probar sus funcionalidades y límites.

Si necesita ayuda sobre cómo usar e implementar esta biblioteca, le sugiero que consulte el código fuente de la página de demostración: verá que es muy fácil de hacer.

Finalmente, para obtener una explicación completa de cuáles pueden ser los problemas relacionados con el uso de hash (y hashbangs), consulte este enlace de Benjamin Lupton.

Erenor Paz
fuente
8

Uso history.pushState()de la API de historial HTML 5.

Consulte la API de historial HTML5 para obtener más detalles.

Prathamesh Rasam
fuente
7

Puede utilizar esta función hermosa y simple para hacerlo en cualquier lugar de su aplicación.

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

No solo puede editar la URL, sino que también puede actualizar el título junto con ella.

Muy útil para todos.

Dheeraj Thedijje
fuente
1
Funciona como un encanto incluso para las anclaswindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD