2015-05-06 23 views
9

Daniel F Pupius opisany problem jak:ember.js przywrócić zwój na historii, Reset przewinąć na link

Wiele stron dostać to źle i to naprawdę denerwujące. Gdy użytkownik nawiguje za pomocą przycisku przewijania do przodu lub do tyłu w przeglądarce, pozycja przewijania powinna być taka sama, jak poprzednio na stronie. To czasami działa poprawnie na Facebooku, ale czasami nie działa. Google+ zawsze traci pozycję przewijania.

W związku z tym istnieje już wiele pytań dotyczących resetowania przewijania do góry strony podczas przeglądania nowej strony. Cookbook również shows how to hook into Route.activate ember.js za:

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

Jednak to tylko rozwiązuje połowę problemu. Gdy użytkownik użyje przycisków wstecz/przewijania do przodu, pozycja przewijania nie zostanie przywrócona, ale po prostu zresetowana.

Istnieje wiele prób rozwiązania tego problemu, wielu po prostu przechowuje pozycję przewijania wewnątrz instancji Ember.Controller, na przykład w tym article. Jest to jednak tylko częściowe rozwiązanie. Jeśli kontroler jest używany wiele razy, tylko jeden stan przewijania zostanie zachowany.

Jak można zachować domyślną implementację przeglądarki przywracania starego stanu przewijania? Tak więc nie rób nic, jeśli Route.activate został wywołany ze zmiany stanu historii html5?

Odpowiedz

14

Właśnie rozwiązałem ten problem w mojej własnej aplikacji.

Jeśli chcesz tylko używać go w miejscach, które tego potrzebują, wystarczy użyć wstawek:

ember g mixin remember-scroll

Następnie w mixins/remember-scroll.js, wymienić:

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

}); 

Jeżeli chcesz automatycznie miesza się ze wszystkimi trasami, a następnie wykonaj następujące czynności.

W interfejsie Ember CLI utwórz nowy inicjator.

ember g initializer remember-scroll

Następnie w initializers/remember-scroll.js wymienić kod z tego:

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

można usunąć pierwszy mixin powyżej, jeśli używasz wersji initializer.

Powoduje to, że wszystkie trasy zapamiętują ostatnią pozycję przewijania (jeśli byłeś tam wcześniej) i stosujesz ją, gdy tam wrócisz.

Chociaż nie polecam umieszczania go na wszystkich trasach, ponieważ użytkownicy mogą nie oczekiwać powrotu do poprzedniej pozycji przewijania, jeśli upłynęło dużo czasu od ich ostatniego.

+0

Myślę, że to nie zapamięta dwóch różnych pozycji przewijania, jeśli kontroler był odwiedzany dwa razy? – bouke

+0

Ten mixin dotyczy trasy, a nie kontrolera. Zapamiętuje pozycję przewijania po opuszczeniu trasy (patrz sekcja "dezaktywuj"), a następnie przywraca ją po powrocie. – JeremyTM

3

Znalazłem the solution by JeremyTM here ogólnie skuteczną. Jednak w moim doświadczeniu użycie metody deactivate prowadzi do niespójności wartości ustawionej na lastScroll podczas przejścia, podczas gdy użycie metody działania trasy prowadzi do zachowania zgodnego zestawu.

Oto modyfikacja jego wstawek, że działa lepiej dla mnie:

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

Uwaga również, że jeszcze w tym uderza mnie jako częściowe rozwiązanie problemu w tym, że to nie resetuje zwój na wszystkich linku kliknięcia (w przeciwieństwie do nawigacji w przeglądarce/zmian w historii). Robi to przy pierwszym kliknięciu linku, który ładuje trasę, ale wszystkie kolejne kliknięcia linku do tej trasy załadują również poprzednią pozycję przewijania, tym samym nie rozpoznając zamierzonego działania użytkownika, aby załadować trasę bez odniesienia do jej poprzedniego zachowania widoku (aka z resetowaną pozycją przewijania).

1

Zainstaluj ten dodatkowy ember ember-router-scroll, aby zresetować przewijanie za pomocą funkcji przywracania historii przewijania. Korzysta z interfejsu API HistoryLocation w przeglądarkach, więc działa po prostu od razu po wyjęciu z pudełka.