Ember.js против скроллинг амнезии

в 11:55, , рубрики: Песочница

В публикации «Семь принципов создания современных веб-приложений» в скроллинг-амнезии были уличены 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.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js