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

Прежде всего, я сделал поиск и не ответил на stackoverflow/google, предоставив мне то, что я хотел.

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

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

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

Спасибо заранее.

Ответы

Ответ 1

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

Если мы посмотрим на 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/

Ответ 2

Если значения, переданные функции, всегда совпадают, вы можете частично применить его с помощью _.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;
  ...
}