Как найти инициированное событие из Backbone.listenTo?

В Backbone я использую новое событие Backbone.listenTo. В одном из моих экземпляров прослушиватель привязан к трем разным событиям, например:

this.listenTo(this._Collection, 'reset add change', this._setCollection);

Он вызывается соответствующим образом, когда он должен, и там нет проблем. Чего я не знаю, так это как узнать, какое событие было вызвано. У меня есть доступ к аргументу e, используя:

_setCollection: function(e) {
    // Do fun stuff
}

Проблема в том, что аргумент e отправляет только копию коллекции и не упоминает, какое событие фактически запускается. Я пробовал e.type и e.target, но этих объектов не существует. Вот копия объекта e из инструментов Chrome Dev:

_byCid: Object
_byId: Object
_events: Object
    add: Array[1]
    change: Array[1]
    remove: Array[1]
    reset: Array[1]
__proto__: Object
_listenerId: "l16"
length: 3
models: Array[3]

Как я могу узнать, какое событие было запущено?

РЕДАКТИРОВАТЬ: Уточнение ответа: хотя помеченный ответ является технически правильным, как указано mu_is_too_short, правильный ответ использует несколько обработчиков и не выполняет этот тип «уловок»


person Brandon    schedule 10.01.2013    source источник


Ответы (1)


Вы не можете определить тип события напрямую, но в некоторых случаях вы можете вывести его из arguments. В каталоге событий сказано следующее:

  • "добавить" (модель, коллекция, параметры) — когда модель добавляется в коллекцию.
  • "сбросить" (коллекция, опции) — когда было заменено все содержимое коллекции.
  • "change" (модель, параметры) — когда атрибуты модели изменились.

К счастью для вас, все три этих события имеют разные параметры, поэтому содержимое arguments будет однозначно (в данном случае) определять инициирующее событие:

  1. Если arguments[0] — это модель, а arguments[1] — это коллекция, то у вас есть событие "add".
  2. Если arguments[0] является коллекцией, то у вас есть событие "reset".
  3. Если arguments[0] — это модель, а arguments.length — это 2, то у вас есть событие "change".

Таким образом, вы можете сделать что-то неприятное и хрупкое, например, в своем _setCollection:

    // M is your model, C is your collection.
    if(arguments[0] instanceof M
    && arguments[1] instanceof C) {
        // An "add" event...
    }
    else if(arguments[0] instanceof C) {
        // A "reset" event...
    }
    else if(arguments[0] instanceof M
         && arguments.length == 2) {
        // A "change" event...
    }
    else {
        console.log('confusion!');
    }

Демонстрация: http://jsfiddle.net/ambiguous/Y9UUX/

Однако я бы не рекомендовал подобные уловки, они громоздкие, хрупкие и могут сломаться, если вы добавите в список больше типов событий. Если вашему обработчику событий нужно знать, какое событие вызвало его, вам лучше использовать отдельные обработчики для каждого типа события: три функции и три вызова listenTo лучше, чем небольшая куча уродливого хакерства.

person mu is too short    schedule 10.01.2013
comment
Ага, полностью согласен. Я обнаружил проблему, потому что я смотрел на событие удаления и содержал все это в одной функции. Я заметил, что аргументы были разными, и должен был указать это в вопросе. В любом случае, спасибо за ваш хакерство. Я буду использовать разные обработчики для каждого. - person Brandon; 10.01.2013