2015-05-06 8 views
9

Daniel F Pupius beschrieben, das Problem so:Ember.js scroll auf Geschichte wiederherstellen, Reset auf Link blättern

Viele Websites bekommen dies falsch und es ist wirklich ärgerlich. Wenn der Benutzer mit der Vorwärts- oder Zurück-Taste des Browsers navigiert, sollte die Bildlaufposition dieselbe sein wie beim letzten Mal auf der Seite. Dies funktioniert manchmal auf Facebook korrekt, manchmal nicht. Google+ scheint immer die Scroll-Position zu verlieren.

Es gibt also bereits zahlreiche Fragen zum Zurücksetzen des Bildlaufs zum Anfang der Seite, wenn Sie zu einer neuen Seite navigieren. Ember.js Kochbuch auch shows how to hook into Route.activate:

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

jedoch nur, löst das Problem halbieren. Wenn der Benutzer die Zurück/Vorwärts-Tasten verwendet, wird die Bildlaufposition nicht wiederhergestellt, sondern einfach zurückgesetzt.

Es gibt einige Versuche, dies zu lösen, viele, indem Sie nur die Bildlaufposition innerhalb der Ember.Controller Instanz speichern, zum Beispiel in dieser article. Dies ist jedoch nur eine Teillösung. Wenn der Controller mehrfach verwendet wird, bleibt nur ein einzelner Bildlaufstatus erhalten.

Wie kann die standardmäßige Browserimplementierung zum Wiederherstellen des alten Bildlaufstatus beibehalten werden? Also, nichts tun, wenn Route.activate ausgelöst wurde von einem html5 Verlaufsstatus ändern?

Antwort

14

Ich habe gerade dieses Problem in meiner eigenen App gelöst.

Wenn Sie es nur an Orten verwenden möchten, die sie benötigen, verwenden Sie nur eine mixin:

ember g mixin remember-scroll

Dann in mixins/remember-scroll.js, ersetzen mit:

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()); 
    }, 

}); 

Wenn Sie es automatisch möchten in alle Routen gemischt, dann folgendes tun.

Erstellen Sie in Ember CLI einen neuen Initialierer.

ember g initializer remember-scroll

Dann in initializers/remember-scroll.js, ersetzen Sie den Code mit diesem:

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 
}; 

Sie können die erste mixin oben entfernen, wenn Sie die initializer Version verwenden.

Dies sollte dazu führen, dass alle Ihre Routen die letzte Scroll-Position speichern (falls Sie schon einmal dort waren) und diese anwenden, wenn Sie dorthin zurückkehren.

Obwohl ich empfehlen würde, es in alle Routen zu setzen, da Benutzer nicht erwarten können, zu einer vorherigen Bildlaufposition zurückzukehren, wenn eine erhebliche Zeit vergangen ist, seit sie zuletzt dort waren.

+0

Ich denke, das wird sich nicht an zwei verschiedene Scroll-Positionen erinnern, wenn der Controller zweimal besucht wurde? – bouke

+0

Diese Mischung gilt für die Route, nicht Controller. Es merkt sich die Scroll-Position beim Verlassen der Route (siehe den Abschnitt "deaktivieren") und stellt sie dann wieder her, wenn Sie zurückkommen. – JeremyTM

3

Ich habe the solution by JeremyTM here gefunden, um allgemein wirksam zu sein. Die Verwendung der Methode deactivate führt jedoch nach meiner Erfahrung zu Inkonsistenzen im Wert lastScroll beim Übergang, während die Verwendung der Aktionsmethode willTransition der Route zu einem konsistenten Mengenverhalten führt.Hier

ist die Modifikation seiner mixin, die besser funktioniert für mich:

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()); 
    } 
    } 
}); 

Hinweis auch, dass dies immer noch erscheint mir als eine Teillösung für das Problem, dass es nicht zurückgesetzt Rolle auf allen Link Klicks (im Gegensatz zu Browsernavigationen/Verlaufsänderungen). Dies geschieht beim ersten Link-Klick, der eine Route lädt. Alle nachfolgenden Link-Klicks auf diese Route laden jedoch auch die vorherige Bildlaufposition. Dadurch wird die beabsichtigte Aktion des Benutzers zum Laden der Route ohne Bezug auf das vorherige Ansichtsverhalten nicht erkannt. aka mit einer Reset-Scroll-Position).

1

Installieren Sie dieses Ember-Addon ember-router-scroll, um den Bildlauf mit Scroll-History-Wiederherstellungsfunktionen zurückzusetzen. Es nutzt die HistoryLocation API der Browser, so dass es sofort einsatzbereit ist.

Verwandte Themen