Передача аргументов к событиям в магистрали

Во-первых, я выполнил поиск, и ни один ответ на stackru / google не дал мне то, что я хотел.

Вот фрагмент моего кода:

//in the view
this.collection.on("add",triggerthis)
this.collection.add(predefinedModel)
triggerthis: function(a, b, c, d){
    //etc.
}

По сути, я хочу иметь возможность передать аргумент при добавлении и получить аргумент в триггере. Это возможно?

Заранее спасибо.

2 ответа

Решение

Вы не можете сделать это так, как вы хотите, без использования недокументированных функций.

Если мы посмотрим на Collection#add мы увидим это:

add: function(models, options) {
  //...
  for (i = 0, l = add.length; i < l; i++) {
    (model = add[i]).trigger('add', model, this, options);
  }
  //...
}

Обратите внимание на четвертый аргумент trigger, И если мы посмотрим на документированный интерфейс для trigger:

спусковой крючок object.trigger(event, [*args])

Триггеры обратного вызова для данного события или разделенный пробелами список событий. Последующие аргументы для триггера будут переданы обратным вызовам событий.

Итак add будет называть слушателей как f(model, collection, options) где options та же options что вы передали Collection#add, В результате, если вы сделаете это:

this.collection.add(predefinedModel, { undocumented: 'arguments' })

тогда вы можете сделать это в вашем обратном вызове:

triggerthis: function(model, collection, options) {
    console.log(options.undocumented);
}

Демо: http://jsfiddle.net/ambiguous/bqWwQ/

Конечно, вы можете туннелировать весь массив или объект через options сюда.

Третий аргумент в пользу "add" события не документированы (по крайней мере, я не могу их найти), ближе всего к документации по этому вопросу есть примечание в записи 0.3.3:

Вездесущий options Аргумент теперь передается в качестве последнего аргумента для всех "change" События.

Я бы не рекомендовал такой подход, но он есть, если он вам нужен; вам, конечно, нужно будет охватить это в вашем наборе тестов, и вы должны быть уверены, что вы не используете какие-либо ключи в options что будет использовать Backbone.


Более безопасный подход - добавить некоторые дополнительные свойства к модели:

model.baggage = { some: 'extra stuff };

а затем очистить это в обратном вызове:

triggerthis: function(model, collection) {
    var baggage = model.baggage;
    delete model.baggage;
    //...
}

Демо: http://jsfiddle.net/ambiguous/M3UaH/

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

Есть также _.bind:

this.collection.on("add", _.bind(function(collection, model, extra) { ... }, context, collection, model, 'whatever you want'));

но это будет связывать аргументы слева направо, поэтому вам нужно будет указать все аргументы, которые понадобятся вашему обратному вызову.

Демо: http://jsfiddle.net/ambiguous/jUpJz/

Если значения, передаваемые в функцию, всегда одинаковы, вы можете частично применить ее, используя _.bind (или родной Function.bind если доступно)

Например, где вы привязываете обработчик к add (при условии, triggerThis это метод на ваш взгляд):

this.collection.on('add', _.bind(this.triggerThis, this, a, b, c, d));

Определение triggerThis:

triggerThis: function(a, b, c, d /*, model, collection, options - if you need them*/) {
  ...
}

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

Например

this.collection.on('add', this.triggerThis, this);
this.collection.add(model, {
  someCustomValue: 'hello';
});

Тогда в вашем обработчике:

triggerThis: function(model, collection, options) {
  var val = options.someCustomValue;
  ...
}
Другие вопросы по тегам