2014-11-06 4 views
1

Я пытаюсь создать приложение Ember, в котором сохраняются положения прокрутки между маршрутами, предоставляя пользователю более приятное впечатление во время просмотра.Сохранение позиции прокрутки в Ember

Ожидаемый результат

Если я прокручиваю 500px вниз на/страницаБ, нажмите ссылку/страницаА, нажмите браузер кнопку назад я должен вернуться в верхней 500px прокрутки.

Фактический результат

При нажатии кнопки браузера назад, верхняя свитка равна высоте/страницаА.

Как воспроизвести

git clone https://github.com/eTilbudsavis/ember-scroll-demo 
cd ember-scroll-demo 
npm install 
ember serve 
open http://localhost:4200/pageb 

Затем прокрутите весь путь до дна, нажмите на ссылку страницаА, а затем нажмите на кнопку браузера назад, и вы должны увидеть эту проблему.

Конечные ноты

Я думаю, что причина такого поведения, когда я нажимаю браузер кнопку назад, браузер пытается прокрутить назад к позиции, которую он имел, прежде чем покинуть этот маршрут. Поскольку Ember пока не отобразил эту точку зрения, браузер не может туда попасть. Он может прокручиваться так далеко, как высота/pagea.

Теперь, что более сложно, если я иду на консоль браузера и вручную устанавливаю верхнюю часть прокрутки после нажатия, ничего не происходит. Кажется, браузер считает, что он находится в правом верхнем углу прокрутки, хотя это не так. Если я сделаю одиночный свиток с помощью мыши, браузер скачет полностью вниз до того места, где должен был быть.

Надеюсь, я объяснил это как можно более кратким. В противном случае, не стесняйтесь спрашивать больше деталей.

Спасибо!

+0

Я обновил свой ответ, он должен теперь работать как Firefox и Chrome браузеры. –

+0

другой ответ, со смесью: http://reefpoints.dockyard.com/2014/05/05/preserve-scroll-position-in-ember-apps.html – givanse

+0

Я пробовал это, но на самом деле это не так особенно в Chrome. – user3365242

ответ

0

Я решил вопрос сам с этим маршрутом Mixin если кто-то хочет использовать его:

`import Ember from 'ember'` 

Ember.$(window).on 'unload', -> 
    $(@).scrollTop 0 

    return 

PreserveScrollMixin = Ember.Mixin.create 
    # @property [Integer] the time to wait before running the scroll callback 
    # 
    scrollingTimeout: 100 

    # As soon as the route initializes, set the min height on the body and the scroll top on the window and listen to 
    # future scroll events. 
    # 
    beforeModel: -> 
     height = @getWithDefault 'controller.height', 0 
     scrollTop = @getWithDefault 'controller.scrollTop', 0 
     onScroll = => 
      Ember.run.debounce @, @runScrolled, @scrollingTimeout 

      return 

     Ember.$('body').css 'min-height', height 
     Ember.$(window).on 'scroll.scrollable', onScroll 
     Ember.$(window).scrollTop scrollTop 

     return 

    # When the route's model is ready, set the scroll top again to be sure. 
    # 
    afterModel: -> 
     scrollTop = @getWithDefault 'controller.scrollTop', 0 

     Ember.run.next @, -> 
      Ember.$(window).scrollTop scrollTop 

      return 

     return 

    # Sets the scroll top for the window. 
    # 
    runScrolled: -> 
     @set 'controller.scrollTop', Ember.$(window).scrollTop() 

     return 

    actions: 
     # When the route appears, allow the body to flow naturally. 
     # 
     didTransition: -> 
      Ember.$('body').css 'min-height', '100%' 

      return 

     # When the route is about to leave, stop listening to scroll events and set the current body height. 
     # 
     willTransition: -> 
      Ember.$(window).off 'scroll.scrollable' 
      @set 'controller.height', Ember.$('body').height() 

      return 

`export default PreserveScrollMixin` 
+0

Теперь вы сохраняете состояние прокрутки внутри контроллера. Если контроллер используется много раз во всем приложении, будет только одно состояние прокрутки, верно? – bouke

+0

Я действительно немного изменил его, так что состояние прокрутки не находится внутри контроллера. Вместо этого он находится в глобальном (модульном) объекте с именем 'scrollTops', где я сохраняю такие изменения следующим образом: scrollTops [@routeName] = Ember. $ (Window) .scrollTop(). – user3365242

+0

Такая же проблема остается, так как теперь вы можете хранить одно состояние прокрутки по маршруту, а не отдельное состояние прокрутки для элемента истории. – bouke

0

Возможно, вам кажется, что вы полагаетесь на состояние прокрутки браузеров ', но вы не указали, какой браузер вы используете.

Я попытался создать длинную страницу и перейти во внешнюю ссылку, а текущий Chrome сохранил состояние прокрутки после возврата, но Firefox этого не сделал.

Таким образом, не полагаясь на браузер, общий ответ на вопрос «сохранение состояния» заключается в использовании queryParams.

Я создал образец со статусом прокрутки, сохраненным в queryParams. Обратите внимание, что я использую replaceState, чтобы браузер не создавал новую запись истории для каждого прокрутки.

App = Ember.Application.create({}); 

App.ApplicationRoute = Ember.Route.extend({ 
    queryParams: { 
    scrollTop: { 
     replace: true 
    } 
    }, 
    setupController: function(controller) { 
    $(window).on('load', function() { 
     $(document).scrollTop(controller.get('scrollTop')); 
    }); 
    } 
}); 

App.ApplicationController = Ember.Controller.extend({ 
    queryParams: ["scrollTop"], 
    scrollTop: 0, 
    handleScroll: function() { 
    this.set('scrollTop', $(document).scrollTop()); 
    }, 
    bindScrollEvent: function() { 
    $(window).on('scroll', Ember.run.bind(this, this.handleScroll)); 
    }.on('init') 
}); 

JSBin - here.

UPDATE: Я заменил образец кода на фиксированную версию, которая фактически работает как в Firefox, так и в Chrome.

+0

Благодарим вас за ответ. Я ценю это! Однако я немного обеспокоен сохранением состояния прокрутки в URL-адресе. Я не могу думать о каких-либо веб-сайтах, которые это делают? Это немного запутывает IMO, чтобы обновлять URL-адрес на каждом прокрутке. Поскольку я задал свой вопрос, я работал над потенциальным решением: https://gist.github.com/anonymous/b51b25ec8d1a36cba752. Это в CoffeeScript - надеюсь, вы не против. Кажется, он работает во всех браузерах. Как вы думаете? – user3365242

+0

Это выглядит хорошо, однако, я не понял из gist, где сохраняется состояние прокрутки (session, localStorage)? Сохранение URL-адреса может быть полезно, если вы хотите передать URL-адрес с сохраненным статусом прокрутки кому-то другому. Я не видел ни одного сайта, который на самом деле это делал. Вы можете быть первыми :) На самом деле, это трудно обойтись без Ember. –

+0

На самом деле я не хочу сохранять состояние прокрутки, когда вы возвращаетесь на сайт после посещения внешнего ресурса. Я хочу, чтобы убедиться, что опыт веб-сайта запомнил позицию прокрутки для каждого маршрута, идущего вперед и назад. – user3365242

Смежные вопросы