Как мне привязать к оконной функции в Ember View?

У меня есть mixin, который автоматически пересчитывает и устанавливает высоту div на размер страницы.

Это работает, но мне кажется глупым быть привязкой к событию jQuery и запускать событие Ember вручную каждый раз, когда он вызывается.

Есть ли способ привязки к событиям окна непосредственно в Ember?

У меня есть упрощенный JSFiddle здесь

Это код:

App.windowWrapper = Ember.Object.create(Ember.Evented,
  resizeTimer: null
  init: ->
    @_super()
    object = this
    $(window).on 'resize', ->
      window.clearTimeout(object.resizeTimer)
      object.resizeTimer = setTimeout( App.windowWrapper.resize, 100)
      true

  resize: ->
    App.windowWrapper.fire('resize')
)

И миксин, который его вызывает.

App.Scrollable = Ember.Mixin.create
  classNames: "scrollable"
  init: ->
    Ember.assert("Scrollable must be mixed in to a View", this instanceof Ember.View)
    @_super()

  didInsertElement: ->
    @_super()
    @calculateHeight()
    App.windowWrapper.on('resize', this, 'calculateHeight')

  willDestroyElement: ->
    App.windowWrapper.off('resize', this, 'calculateHeight')
    @_super()

  calculateHeight: ->
    offset       = @$().offset().top
    windowHeight = $(window).height()
    @$().css('height', windowHeight - offset)

Ответ 1

Нет ничего плохого в регистрации вашего собственного обработчика событий с помощью jQuery для чего-то вроде этого.

У Ember нет обработки событий окна в настоящее время.

Я также предлагаю попытаться найти решение, которое не полагалось бы на глобальные переменные.

Ответ 2

Я знаю, что я опаздываю на несколько лет, но я искал решение той же проблемы и нашел это:

jQuery(window).on('resize', Ember.run.bind(this, this.handleResize));

(источник: Ember.js oficial)

**** P.S. О реализации этого небольшого трюка - я не знаю, можно ли использовать его в методе контроллера и запускать init (как прокомментировал denis.peplin), я фактически привязываю событие к функции routeController. Я не знаю, лучше ли это, но это работает как прелесть в моем приложении.

Ответ 3

И пример кода для ответа Itay Hamashmid:

App.ApplicationController = Ember.Controller.extend({
  handleResize: function() {
    console.log('resized');
  },
  bindResizeEvent: function() {
    jQuery(window).on('resize', Ember.run.bind(this, this.handleResize));
  }.on('init')
});

Ответ 4

Я не думаю, что это возможно с помощью Ember.js - единственное место, где он обеспечивает встроенную обработку событий DOM, это для Ember.View(щелчок и т.д.) и, возможно, в других классах, связанных с представлением.

Мы также использовали аналогичные подходы к вашему решению для обработки особых случаев, подобных этому!

Ответ 5

Для тех, кто ищет новые ответы или просто избавится от jquery...

В моем случае я просто хочу узнать, изменилось ли окно до ширины элемента calc.

import Component from '@ember/component';

export default Component.extend({
  size: window.innerWidth,

  init() {
    this._super(...arguments);

    window.addEventListener('resize', ()=> this.set('size', window.innerWidth));
  }
});

Да, я знаю, что нет способа отменить привязку анонимной функции, но я искал и не могу найти хорошие ответы...

Я думаю, чтобы реорганизовать это, чтобы использовать jquery, но в ограниченной области, например:

import Component from '@ember/component';
import $ from 'jquery';

export default Component.extend({
  size: window.innerWidth,

  init() {
    this._super(...arguments);

    $(document.querySelector('#something'))
              .on('resize', (e)=> this.set('size', e.target.innerWidth));
  }
});

И этот слушатель будет жить до тех пор, пока этот компонент не будет жить!