Pregunta ¿Cómo uso window.history en JavaScript?


Encontré muchas preguntas sobre esto en Stack Overflow, pero todas eran muy específicas sobre ciertas partes. Encontré esta pregunta cuyas respuestas proporcionan buenas referencias, pero en realidad no explican cómo funciona todo, y sus ejemplos apenas hacen nada. Quiero saber más sobre cómo funciona todo junto, y quiero usar JavaScript vanidoso.

(Además, muchas de las respuestas a otras preguntas tienen años de antigüedad).


5
2017-07-21 00:22


origen


Respuestas:


EMPEZANDO

Antes que nada, puedes eliminar el window parte. Sólo history funciona bien. Pero antes de ver cómo funciona todo junto, necesitamos saber qué podemos usar.

Eventos importantes

window.onload

Este evento se dispara cada vez que se carga su página web. Hay dos casos que desencadenarán este evento:

  1. Cuando se navega por su página web desde otra página web. Tenga en cuenta que escribí webpágina, no websitio. Mover entre páginas en el mismo sitio activará este evento.
  2. Justo después de que su página web esté actualizada.

window.onpopstate

Este evento se dispara cuando navega entre los estados históricos que  haber instalado. Su navegador establece automáticamente los estados históricos (en nulo) durante la navegación normal, pero navegar hacia / desde estos estados no activará este evento.

window.onunload

Este evento se dispara cada vez que se descarga su página web. Hay dos casos que dispararán este evento:

  1. Cuando navegas a otra página web desde tu página web.
  2. Justo antes de que su página web se actualice.

Objetos importantes

La interfaz de historial contiene cinco funciones (descritas a continuación), dos objetos de solo lectura (descritos aquí), y funciona un poco como un lista enlazada. Los dos objetos contenidos en cada 'enlace' del objeto histórico son:

  • longitud: este es el número de estados del historial de la ventana del navegador actual. Comienza en 1.
  • estado: este es un objeto de JavaScript que puede contener prácticamente cualquier cosa. Es null por defecto.

Puede acceder a ellos llamando history.length y history.state respectivamente, aunque history.state solo se puede usar para obtener corriente estado de la historia

Funciones importantes

history.go (distancia)

Esta función hace lo mismo que presionar el botón de retroceder o avanzar en su navegador, con la funcionalidad adicional de poder especificar exactamente hasta dónde quiere ir. Por ejemplo, history.go(3) tiene el mismo efecto que si presionara el botón de avance tres veces, sin cargar las páginas entre las ubicaciones de inicio y final. Un valor negativo también lo hará retroceder a través de su historial. history.go(0), history.go()e incluso history.go(NaN) tiene el mismo efecto que actualizar la página (esto no activa el popstate evento). Si no puede avanzar / retroceder hasta donde se especifique, la función no hará nada.

history.back ()

Esta función tiene la misma funcionalidad que el botón Atrás en su navegador. Es equivalente a history.go(-1). Si no puede volver, la función no hará nada.

history.forward ()

Esta función tiene la misma funcionalidad que el botón de avance de su navegador. Es equivalente a history.go(1). Si no puede avanzar, la función no hará nada.

history.replaceState (estado, título [, ubicación])

Esta función reemplaza el estado del historial actual. Se necesitan tres argumentos, aunque el último es opcional. Los argumentos son:

  • estado - Este es el argumento más importante. El objeto que le dé a este argumento se guardará en history.state para una recuperación posterior. Esta es una copia profunda, por lo que si luego modifica el objeto original, no cambiará el estado guardado. También puedes configurar esto para null, pero si no vas a usarlo, no tiene mucho sentido usar history en absoluto.
  • title: el estándar HTML sugiere que el navegador puede usar una cadena que se transfiera a este argumento en la interfaz de usuario, pero actualmente ningún navegador hace nada con él.
  • ubicación: este argumento le permite cambiar la URL relativa a la página actual. No se puede usar para cambiar la URL a la de otro sitio web, pero se puede usar para cambiar la URL a la de otra página en tu sitio web. Sin embargo, desaconsejaría esto, ya que la página no se vuelve a cargar aunque la URL sea de otra página. El uso de atrás / adelante mostrará la URL modificada, pero no cambiará la página y activará popstate más bien que load o unload. Actualizar la página después de cambiar su URL cargará la página especificada por la URL en lugar de la página en la que estaba anteriormente. Esta funcionalidad podría usarse para proporcionar un enlace a su página en su estado actual, pero recomendaría solo cambiar la cadena de consulta en lugar de la URL completa. Si este argumento no se utiliza, la URL no cambiará.

history.pushState (estado, título [, ubicación])

Esta función funciona igual que history.replaceState, excepto que pone el nuevo estado después El estado actual en lugar de reemplazar el estado actual. Toda la historia indica que se pudo haber accedido previamente con forward se descartan, y el nuevo estado se convierte en el estado actual.

MONTAJE DE LAS PIEZAS

La interfaz de historial es muy útil para permitir a los usuarios navegar a través del contenido generado dinámicamente desde su navegador sin tener que volver a cargar toda la página, pero debe tener en cuenta todas las cosas que los usuarios podrían hacer y que podrían afectar el historial.

  1. La primera vez que navega hacia su página
    • ¿Deben saludar a sus usuarios con un menú / lista, algún contenido específico generado dinámicamente, o tal vez algún contenido aleatorio generado dinámicamente?
    • ¿Su página se mostrará correctamente sin history, o incluso JavaScript?
  2. Utilizando back/forward para volver a tu pagina
    • ¿Deberían los usuarios ver lo mismo que vieron por primera vez o deberían ver el resultado de su visita reflejado en el contenido? (Un mensaje de "Bienvenida de Atrás" puede ser un buen toque para algunos, pero una distracción no deseada para otros).
  3. Refrescando tu pagina
    • ¿Debería obtener una nueva página, volver a la página de inicio o volver a cargar la misma página? (Sus usuarios probablemente no esperarán eso último si la URL no ha cambiado).
  4. Utilizando back/forward desde una página actualizada
    • ¿Debería obtener nuevo contenido relativo a la página actualizada o volver a cargar el estado guardado anteriormente?
  5. Navegando lejos de tu página
    • ¿Necesitas guardar algo antes de irte?
  6. Regresando a su página a través de un enlace profundo
    • ¿Tiene un código en su lugar para reconocer y manejar un enlace profundo?

Tenga en cuenta que no hay manera de eliminar un estado guardado (que no sea un caso específico con pushState() mencionado anteriormente). Solo puedes reemplazarlo con nuevo contenido.

PONIENDOLO TODO JUNTO

Ya que esto está empezando a ponerse un poco largo, terminemos con algo de código.

// This function is called when the page is first loaded, when the page is refreshed,
// and when returning to the page from another page using back/forward.
// Navigating to a different page with history.pushState and then going back
// will not trigger this event as the page is not actually reloaded.
window.onload = function() {
  // You can distinguish a page load from a reload by checking performance.navigation.type.
  if (window.performance && window.PerformanceNavigation) {
    let type = performance.navigation.type;
    if (type == PerformanceNavigation.TYPE_NAVIGATE) {
      // The page was loaded.
    } else if (type == PerformanceNavigation.TYPE_RELOAD) {
      // The page was reloaded.
    } else if (type == PerformanceNavigation.TYPE_BACK_FORWARD) {
      // The page was navigated to by going back or forward,
      // though *not* from a history state you have set.
    }
  }

  // Remember that the browser automatically sets the state to null on the
  // first visit, so if you check for this and find it to be null, you know
  // that the user hasn't been here yet.
  if (history.state == null) {
    // Do stuff on first load.
  } else {
    // Do stuff on refresh or on returning to this page from another page
    // using back/forward. You may want to make the window.onpopstate function
    // below a named function, and just call that function here.
  }

  // You can of course have code execute in all three cases. It would go here.

  // You may also wish to set the history state at this time. This could go in the
  // if..else statement above if you only want to replace the state in certain
  // circumstances. One reason for setting the state right away would be if the user
  // navigates to your page via a deep link.
  let state = ...; // There might not be much to set at this point since the page was
                   // just loaded, but if your page gets random content, or time-
                   // dependent content, you may want to save something here so it can
                   // be retrieved again later.
  let title = ...; // Since this isn't actually used by your browser yet, you can put
                   // anything you want here, though I would recommend setting it to
                   // null or to document.title for when browsers start actually doing
                   // something with it.
  let URL = ...;   // You probably don't want to change the URL just yet since the page
                   // has only just been loaded, in which case you shouldn't use this
                   // variable. One reason you might want to change the URL is if the
                   // user navigated to this page with a query string in the URL. After
                   // reading the query string, you can remove it by setting this
                   // variable to: location.origin + location.pathname
  history.replaceState(state, title, URL); // Since the page has just been loaded, you
                                           // don't want to push a new state; you should
                                           // just replace the current state.
}

// This function is called when navigating between states that you have set.
// Since the purpose of `history` is to allow dynamic content changes without
// reloading the page (ie contacting the server), the code in this function
// should be fairly simple. Just things like replacing text content and images.
window.onpopstate = function() {
  // Do things with history.state here.
}

// This function is called right before the page is refreshed, and right
// before leaving the page (not counting history.replaceState). This is
// your last chance to set the page's history state before leaving.
window.onunload = function() {
  // Finalize the history state here.
}

Note que nunca llamé history.pushState en cualquier sitio. Esto es porque history.pushState No se debe llamar a ninguna parte en estas funciones. Debería llamarlo la función que realmente cambia la página de forma que desee que los usuarios puedan usar el botón Atrás para deshacer.

Entonces, en conclusión, una configuración genérica podría funcionar así:

  • Comprobar if (history.state == null) en el window.onload función.
    • Si es verdadero, sobrescriba el estado del historial con información nueva.
    • Si es falso, usa el estado del historial para restaurar la página.
  • Mientras el usuario está navegando por la página, llame history.pushState cuando suceden cosas importantes que se deben poder deshacer con el botón Atrás.
  • Si / Cuando el usuario usa su botón de retroceso y el popstate se activa el evento, use el estado de historial que configuró para devolver la página a su estado anterior.
    • Haga lo mismo si / cuando el usuario utiliza su botón de avance.
  • Utilizar el unload Evento para finalizar el estado del historial antes de que el usuario abandone la página.

23
2017-07-21 00:22



Preguntas populares