В публикации «Семь принципов создания современных веб-приложений» в скроллинг-амнезии были уличены Facebook и Twitter.
При чтении статьи подумал, что в Ember приложении состояние скроллинга можно сохранять в queryParams. Вкратце: это такая магия, позволяющая связывать переменные контроллера и параметры URL, сохраняя таким образом состояние приложения.
Буквально на следующий день после прочтения статьи мне попался вопрос на StackOverflow, где вопрошавший удивляется, почему у него не запоминается позиция скроллинга после перехода по ссылке и возврата обратно. Заинтересовался, насколько просто (или непросто) на самом деле решается эта проблема в Ember.
После недолгих экспериментов с queryParams и привязкой jQuery Events к Ember, пришел к коду контроллера в девять строк:
App.ApplicationController = Ember.Controller.extend({
queryParams: ["scrollTop"],
scrollTop: 0,
handleScroll: function() {
this.set('scrollTop', $('body').scrollTop());
},
bindScrollEvent: function() {
$('body').scrollTop(this.get('scrollTop'));
$(window).on('scroll', Ember.run.bind(this, this.handleScroll));
}.on('init')
});
Подключив переменную scrollTop к queryParams и выставив значение по умолчанию, остается отслеживать положение скроллинга при его изменении, записывать новое положение в переменную, а при новой инициализации контроллера (то есть при возврате обратно после перехода по внешней ссылке) переводить скроллинг в сохраненное положение.
Еще одна маленькая деталь. При каждом изменении скроллинга, в историю браузера будет записываться новая ссылка. В данном случае это не нужно, историю лучше перезаписывать:
App.ApplicationRoute = Ember.Route.extend({
queryParams: {
scrollTop: {
replace: true
}
},
});
Итого пример приложения на JSBin занимает всего 21 строку, вместе с инициализацией Ember, без ущерба для читаемости кода. Хорошая демонстрация мощи queryParams.