2015-05-06 12 views
9

Daniel F Pupius descritto il problema come:Ember.js ripristino di scorrimento sulla storia, reimpostare scorrere sul collegamento

Un sacco di siti ottenere questo torto ed è davvero fastidioso. Quando l'utente naviga utilizzando il pulsante avanti o indietro del browser, la posizione di scorrimento dovrebbe essere la stessa dell'ultima volta che erano nella pagina. Questo a volte funziona correttamente su Facebook, ma a volte no. Google+ sembra sempre perdere la posizione di scorrimento.

Quindi ci sono già numerose domande su come reimpostare lo scorrimento nella parte superiore della pagina durante la navigazione in una nuova pagina. Cookbook di Ember.js anche shows how to hook into Route.activate:

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

Tuttavia questo solo risolve dimezzare il problema. Quando l'utente utilizza i pulsanti Indietro/Avanti, la posizione di scorrimento non verrà ripristinata, ma semplicemente ripristinata.

Ci sono alcuni tentativi per risolvere questo, molti semplicemente memorizzando la posizione di scorrimento all'interno dell'istanza Ember.Controller, ad esempio in questo article. Tuttavia questa è solo una soluzione parziale. Se il controller viene utilizzato più volte, verrà mantenuto solo un singolo stato di scorrimento.

Come si può conservare l'implementazione predefinita del browser per ripristinare il vecchio stato di scorrimento? Quindi, non eseguire nulla se è stato attivato da una modifica dello stato della cronologia html5?

risposta

14

Ho appena risolto questo problema nella mia app.

Se si desidera utilizzare solo in luoghi che ne hanno bisogno, basta usare un mixin:

ember g mixin remember-scroll

Poi, nel mixins/remember-scroll.js, sostituire 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()); 
    }, 

}); 

Se si desidera automaticamente mescolato in tutte le rotte, quindi effettuare le seguenti operazioni.

Nella CLI di Ember, creare un nuovo initialier.

ember g initializer remember-scroll

Poi, nel initializers/remember-scroll.js, sostituire il codice con questo:

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

È possibile rimuovere il primo mixin sopra, se si sta utilizzando la versione di inizializzazione.

Questo dovrebbe far ricordare a tutte le rotte l'ultima posizione di scorrimento (se ci sei già stato prima), e applicarla quando torni lì.

Anche se mi raccomando di non inserirlo in tutte le rotte, dal momento che gli utenti non possono aspettarsi di tornare a una posizione di scorrimento precedente se è trascorso un periodo di tempo significativo da quando erano lì.

+0

Penso che questo non ricorderà due diverse posizioni di scorrimento se il controller è stato visitato due volte? – bouke

+0

Questo mixin si applica al percorso, non al controller. Ricorda la posizione di scorrimento mentre lasci il percorso (vedi la sezione 'disattiva '), quindi ripristina quando torni. – JeremyTM

3

Ho trovato the solution by JeremyTM here generalmente efficace. Tuttavia, utilizzando il metodo deactivate nella mia esperienza, si verificano incoerenze nel valore impostato su lastScroll durante la transizione mentre l'utilizzo del metodo di azione willTransition del percorso porta a un comportamento coerente dell'insieme.

Ecco la modifica alla sua intermedia che funziona meglio per me:

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

Nota anche che questo mi colpisce ancora come una soluzione parziale al problema in quanto non reimposta scorrimento su tutti i Link clic (a differenza delle navigazioni del browser/modifiche alla cronologia). Lo fa sul primo clic del collegamento che carica un percorso, ma tutti i clic successivi del collegamento a tale percorso caricheranno anche la posizione di scorrimento precedente, non riuscendo quindi a riconoscere l'azione desiderata dell'utente per caricare il percorso senza fare riferimento al comportamento della vista precedente (aka con una posizione di scorrimento di ripristino).

1

Installare questo componente aggiuntivo ember-router-scroll per ripristinare lo scorrimento con funzionalità di ripristino della cronologia di scorrimento. Fa uso dell'API HistoryLocation dei browser in modo che funzioni immediatamente.