ember.js scroll html5-history

Ember.js restaura el desplazamiento en el historial, restablece el desplazamiento en el enlace



scroll html5-history (3)

Acabo de resolver este problema en mi propia aplicación.

Si solo quieres usarlo en lugares que lo necesitan, solo usa un mixin:

ember g mixin remember-scroll

Luego, en mixins/remember-scroll.js , reemplace con:

import Ember from ''ember''; export default Ember.Mixin.create({ scrollSelector: window, activate: function() { this._super.apply(this, arguments); var self = this; if( this.get(''lastScroll'') ){ Ember.run.next(function(){ Ember.$(self.scrollSelector).scrollTop(self.get(''lastScroll'')); }); } else { Ember.$(this.scrollSelector).scrollTop(0); } }, deactivate: function() { this._super.apply(this, arguments); this.set(''lastScroll'',Ember.$(this.scrollSelector).scrollTop()); }, });

Si desea que se mezcle automáticamente en todas las rutas, haga lo siguiente.

En Ember CLI, cree una nueva inicial.

ember g initializer remember-scroll

Luego, en initializers/remember-scroll.js , reemplace el código con esto:

import Ember from "ember"; var rememberScroll = Ember.Mixin.create({ scrollSelector: window, activate: function() { this._super.apply(this, arguments); var self = this; if( this.get(''lastScroll'') ){ Ember.run.next(function(){ Ember.$(self.scrollSelector).scrollTop(self.get(''lastScroll'')); }); } else { Ember.$(this.scrollSelector).scrollTop(0); } }, deactivate: function() { this._super.apply(this, arguments); this.set(''lastScroll'',Ember.$(this.scrollSelector).scrollTop()); }, }); export function initialize(/* container, application */) { Ember.Route.reopen(rememberScroll); } export default { name: ''remember-scroll'', initialize: initialize };

Puede eliminar la primera mixin anterior si está utilizando la versión de inicializador.

Esto debería hacer que todas tus rutas recuerden la última posición de desplazamiento (si has estado allí antes) y aplicarla cuando regreses allí.

Aunque recomendaría no colocarlo en todas las rutas, ya que los usuarios no pueden esperar regresar a una posición de desplazamiento anterior si ha pasado una cantidad significativa de tiempo desde la última vez que estuvieron allí.

Daniel F Pupius describió el problema como:

Muchos sitios se equivocan y es realmente molesto. Cuando el usuario navega utilizando el botón de avance o retroceso del navegador, la posición de desplazamiento debe ser la misma que la última vez que se encontraba en la página. Esto a veces funciona correctamente en Facebook, pero a veces no. Google+ siempre parece perder tu posición de desplazamiento.

Por lo tanto, ya existen numerosas preguntas sobre cómo restablecer el desplazamiento en la parte superior de la página al navegar a una página nueva. El libro de cocina de Ember.js también muestra cómo enganchar en Route.activate :

export default Ember.Mixin.create({ activate: function() { this._super(); window.scrollTo(0,0); } });

Sin embargo, esto solo resuelve reducir a la mitad el problema. Cuando el usuario usa los botones retroceder / avanzar, la posición de desplazamiento no se restaurará, sino que simplemente se reiniciará.

Hay bastantes intentos para resolver esto, muchos simplemente almacenando la posición de desplazamiento dentro de la instancia de Ember.Controller , por ejemplo en este artículo . Sin embargo, esta es solo una solución parcial. Si el controlador se usa varias veces, solo se conservará un solo estado de desplazamiento.

¿Cómo se puede preservar la implementación del navegador predeterminado para restaurar el estado de desplazamiento anterior? Por lo tanto, ¿no hace nada si se activó Route.activate partir de un cambio de estado de la historia html5?


Instale este complemento de brasas Ember -router-scroll para restablecer el desplazamiento con las capacidades de restauración del historial de desplazamiento. Hace uso de la API HistoryLocation de los navegadores para que funcione recién salido de la caja.


He encontrado que la solución de JeremyTM aquí es generalmente efectiva. Sin embargo, usar el método de deactivate en mi experiencia genera inconsistencias en el valor establecido para lastScroll en la transición, mientras que el método de acción willTransition la ruta conduce a un comportamiento de conjunto consistente.

Aquí está la modificación de su mixin que funciona mejor para mí:

import Ember from ''ember''; export default Ember.Mixin.create({ activate: function() { this._super.apply(this, arguments); var self = this; if(this.get(''lastScroll'')){ Ember.run.next(function(){ Ember.$(window).scrollTop(self.get(''lastScroll'')); }); } else { Ember.$(window).scrollTop(0); } }, actions: { willTransition: function() { this._super.apply(this, arguments); this.set(''lastScroll'', Ember.$(window).scrollTop()); } } });

Tenga en cuenta también que esto todavía me parece una solución parcial al problema, ya que no restablece el desplazamiento en todos los clics de enlace (a diferencia de los cambios de navegación / historial del navegador). Lo hace en el primer clic de enlace que carga una ruta, pero todos los clics de enlace posteriores a esa ruta cargarán también la posición de desplazamiento anterior, por lo que no reconocerá la acción prevista del usuario para cargar la ruta sin referencia a su comportamiento de vista anterior ( aka con una posición de desplazamiento de reinicio).