Каков наилучший способ обработки событий в Ember.js?

Я начинаю изучать Ember, и неясно, какой лучший, наиболее приемлемый или даже предназначенный для обработки событий. Допустимо ли проверять цель в аргументе события функции кликов, должен ли я создавать новое представление для каждого элемента, для которого требуется событие, отличное от {{action}}, или что-то совершенно другое?

Ответ 1

IMO вы должны использовать {{action}}, где это возможно. Если вы хотите присоединить события к тегу в шаблоне, используйте {{action}}; нет необходимости создавать новый вид:

<a {{action showPosts href=true}}>All Posts</a>

<form {{action validate target="controller"}}>
  // ...
</form>

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

// Template
<ul>
  {{#each post in controller}}
    {{#view App.PostView}}
      {{title}}
      {{#if view.showDetails}}
        <span>{{summary}}</span>
      {{/if}}
    {{/view}}
  {{/each}}
</ul>

// View
App.PostView = Ember.View.extend({
   tagName: li,
   classNames: ['post-item'],
   mouseEnter: function(event) {
     this.set('showDetails', true);
   },

   mouseLeave: function(event) {
     this.set('showDetails', false);
   }
});

Как нам нужно захватить как mouseEnter, так и mouseLeave (чтобы показать и скрыть детали сообщения соответственно), лучше сделать это в представлении, избегая слишком много логики в шаблонах. Альтернативным способом для этого было бы использовать столько вложенных тегов, сколько количество событий, которые мы хотим обработать (в нашем случае 2):

// Template
<ul>
  {{#each post in controller}}
    <li class="post-item" {{action showTheDetails post on="mouseEnter" target="controller"}}>
    <span class="dummy" {{action hideTheDetails post on="mouseLeave" target="controller"}}
      {{title}}
      {{#if post.showDetails}}
        <span>{{summary}}</span>
      {{/if}}
    </span<
    </li>
  {{/each}}
</ul>

И затем в контроллере:

// Controller
App.PostsController = Ember.ArrayController.extend({
   showTheDetails: function(event) {
     var post = event.context;
     post.set('showDetails', true);
   },

   hideTheDetails: function(event) {
     var post = event.context;
     post.set('showDetails', false);
   }
});

Но я думаю, вы согласитесь, что это уродливее. См. здесь.


В тех случаях, когда вы хотите использовать представления управления Ember (Ember.TextField, Ember.TextArea и т.д.) у вас нет выбора, кроме как захватить события в представлении. Поэтому вы расширяете представление управления и определяете обработчики событий в представлении:

// Template
<legend>Add a comment</legend>
{{view App.CommentInputField valueBinding="comment"}}

// View
App.CommentInputField = Ember.TextField.extend({ 
  focusOut: function(event) {
    this.get('controller').validateComment();
  },

  keyDown: function(event) {
    if (event.keyCode === 13) { // Enter key
      this.get('controller').createComment();
      return false;
    }
  }
});