Spec-Zone.ru › Backbone.js

Backbone.js

Backbone.Events

Events — это модуль, который можно примешать к любому объекту, предоставив ему возможность привязывать и вызывать пользовательские именованные события. События не нужно объявлять до их привязки, и им можно передавать аргументы. Например:

var object = {};

_.extend(object, Backbone.Events);

object.on("alert", function(msg) {
  alert("Triggered " + msg);
});

object.trigger("alert", "an event");

Например, чтобы создать удобный диспетчер событий, который может координировать события между разными частями приложения: var dispatcher = _.clone(Backbone.Events)

onobject.on(event, callback, [context])Псевдоним: bind
Привязать функцию callback к объекту. Функция обратного вызова будет вызвана при каждом возникновении события event. Если на странице много разных событий, принято использовать двоеточия для их группировки по пространствам имён: "poll:start" или "change:selection". Строка события также может представлять собой разделённый пробелами список нескольких событий...

book.on("change:title change:author", ...);

Функции обратного вызова, привязанные к специальному событию "all", будут вызваны при возникновении любого события; имя события передаётся первым аргументом. Например, чтобы перенаправить все события одного объекта другому:

proxy.on("all", function(eventName) {
  object.trigger(eventName);
});

Все методы событий Backbone также поддерживают синтаксис карты событий в качестве альтернативы позиционным аргументам:

book.on({
  "change:author": authorPane.update,
  "change:title change:subtitle": titleView.update,
  "destroy": bookView.remove
});

Чтобы передать значение context для this при вызове функции обратного вызова, укажите необязательный последний аргумент: model.on('change', this.render, this) или model.on({change: this.render}, this).

offobject.off([event], [callback], [context])Псевдоним: unbind
Удалить ранее привязанную к объекту функцию callback. Если context не указан, будут удалены все варианты функции обратного вызова с разными контекстами. Если функция обратного вызова не указана, будут удалены все функции обратного вызова для события event. Если событие не указано, будут удалены функции обратного вызова для всех событий.

// Removes just the `onChange` callback.
object.off("change", onChange);

// Removes all "change" callbacks.
object.off("change");

// Removes the `onChange` callback for all events.
object.off(null, onChange);

// Removes all callbacks for `context` for all events.
object.off(null, null, context);

// Removes all callbacks on `object`.
object.off();

Обратите внимание: вызов model.off(), например, действительно удалит все события модели, включая события, которые Backbone использует для внутреннего учёта.

triggerobject.trigger(event, [*args])
Вызвать функции обратного вызова для указанного события event или разделённого пробелами списка событий. Последующие аргументы метода trigger будут переданы функциям обратного вызова событий.

onceobject.once(event, callback, [context])
Аналогично on, но привязанная функция обратного вызова будет вызвана только один раз, после чего её привязка будет удалена. Удобно, чтобы указать: «В следующий раз, когда произойдёт X, сделай это». Если с помощью синтаксиса с разделением пробелами передано несколько событий, событие сработает один раз для каждого переданного события, а не один раз для комбинации всех событий.

listenToobject.listenTo(other, event, callback)
Заставить объект прослушивать определённое событие другого объекта (other). Преимущество этой формы перед other.on(event, callback, object) в том, что listenTo позволяет объекту отслеживать события, чтобы впоследствии удалить их все сразу. Функция callback всегда будет вызвана с объектом в качестве контекста.

view.listenTo(model, 'change', view.render);

stopListeningobject.stopListening([other], [event], [callback])
Заставить объект прекратить прослушивание событий. Вызовите stopListening без аргументов, чтобы объект удалил все свои зарегистрированные функции обратного вызова... либо укажите точнее, какие события нужно удалить: прослушиваемые для определённого объекта, конкретного события или функции обратного вызова.

view.stopListening();

view.stopListening(model);

listenToOnceobject.listenToOnce(other, event, callback)
Аналогично listenTo, но привязанная функция обратного вызова будет вызвана только один раз, после чего её привязка будет удалена.

Каталог событий
Ниже приведён полный список встроенных событий Backbone с аргументами. Вы также можете вызывать собственные события для моделей, коллекций и представлений по своему усмотрению. Сам объект Backbone примешивает Events и может использоваться для отправки любых глобальных событий, необходимых приложению.

  • "add" (model, collection, options) — когда модель добавляется в коллекцию.
  • "remove" (model, collection, options) — когда модель удаляется из коллекции.
  • "update" (collection, options) — единичное событие, вызываемое после добавления, удаления или изменения любого количества моделей в коллекции.
  • "reset" (collection, options) — когда всё содержимое коллекции было сброшено.
  • "sort" (collection, options) — когда коллекция была повторно отсортирована.
  • "change" (model, options) — когда атрибуты модели изменились.
  • "changeId" (model, previousId, options) — когда идентификатор модели был обновлён.
  • "change:[attribute]" (model, value, options) — когда обновлён определённый атрибут.
  • "destroy" (model, collection, options) — когда модель уничтожена.
  • "request" (model_or_collection, xhr, options) — когда модель или коллекция отправила запрос на сервер.
  • "sync" (model_or_collection, response, options) — когда модель или коллекция успешно синхронизирована с сервером.
  • "error" (model_or_collection, xhr, options) — когда запрос модели или коллекции к серверу завершился ошибкой.
  • "invalid" (model, error, options) — когда проверка модели на клиенте завершается неудачей.
  • "route:[name]" (params) — вызывается маршрутизатором при совпадении с определённым маршрутом.
  • "route" (route, params) — вызывается маршрутизатором при совпадении с любым маршрутом.
  • "route" (router, route, params) — вызывается системой истории при совпадении с любым маршрутом.
  • "notfound" () — вызывается системой истории, если не удалось сопоставить ни один маршрут.
  • "all" — это специальное событие вызывается при срабатывании любого события; имя события передаётся первым аргументом, за которым следуют все аргументы вызова.

Как правило, при вызове функции, генерирующей событие (model.set, collection.add и так далее...), чтобы предотвратить вызов события, можно передать {silent: true} в качестве параметра. Обратите внимание: это редко, а возможно, и никогда не бывает хорошей идеей. Обычно лучше передать определённый флаг в параметрах функции обратного вызова события, чтобы она могла проверить его и при необходимости проигнорировать событие.

Backbone.Model

Модели — основа любого приложения на JavaScript. Они содержат интерактивные данные, а также значительную часть связанной с ними логики: преобразования, проверки, вычисляемые свойства и управление доступом. Расширьте Backbone.Model методами, специфичными для вашей предметной области, а Model предоставит базовый набор функций для управления изменениями.

Следующий пример искусственный, но он демонстрирует определение модели с пользовательским методом, установку атрибута и вызов события, связанного с изменениями этого атрибута. После однократного выполнения этого кода в консоли браузера станет доступен sidebar, с которым можно поэкспериментировать.

var Sidebar = Backbone.Model.extend({
  promptColor: function() {
    var cssColor = prompt("Please enter a CSS color:");
    this.set({color: cssColor});
  }
});

window.sidebar = new Sidebar;

sidebar.on('change:color', function(model, color) {
  $('#sidebar').css({background: color});
});

sidebar.set({color: 'white'});

sidebar.promptColor();

extendBackbone.Model.extend(properties, [classProperties])
Чтобы создать собственный класс Model, расширьте Backbone.Model и укажите свойства экземпляра (properties), а также необязательные свойства класса (classProperties), которые будут добавлены непосредственно к функции-конструктору.

extend правильно настраивает цепочку прототипов, поэтому подклассы, созданные с помощью extend, можно расширять и наследовать сколько угодно раз.

var Note = Backbone.Model.extend({

  initialize: function() { ... },

  author: function() { ... },

  coordinates: function() { ... },

  allowedToEdit: function(account) {
    return true;
  }

});

var PrivateNote = Note.extend({

  allowedToEdit: function(account) {
    return account.owns(this);
  }

});

Краткое замечание о super: в JavaScript нет простого способа вызвать родительскую реализацию — функцию с таким же именем, определённую выше в цепочке прототипов. Если вы переопределяете основную функцию, например set или save, и хотите вызвать реализацию родительского объекта, придётся явно вызвать её, примерно так:

var Note = Backbone.Model.extend({
  set: function(attributes, options) {
    Backbone.Model.prototype.set.apply(this, arguments);
    ...
  }
});

preinitializenew Model([attributes], [options])
Используется с моделями в виде классов ES. Если определить метод preinitialize, он будет вызван при создании модели, до выполнения логики её инициализации.

class Country extends Backbone.Model {
    preinitialize({countryCode}) {
      this.name = COUNTRY_NAMES[countryCode];
    }

    initialize() { ... }
}

constructor / initializenew Model([attributes], [options])
При создании экземпляра модели можно передать начальные значения атрибутов, которые будут установлены для модели. Если определить функцию initialize, она будет вызвана при создании модели.

new Book({
  title: "One Thousand and One Nights",
  author: "Scheherazade"
});

В редких случаях, если требуется более сложное поведение, можно переопределить constructor, заменив фактическую функцию-конструктор модели.

var Library = Backbone.Model.extend({
  constructor: function() {
    this.books = new Books();
    Backbone.Model.apply(this, arguments);
  },
  parse: function(data, options) {
    this.books.reset(data.books);
    return data.library;
  }
});

Если передать {collection: ...} в качестве параметра, модель получит свойство collection, которое указывает, к какой коллекции принадлежит модель, и помогает вычислить её url. Свойство model.collection обычно создаётся автоматически при первом добавлении модели в коллекцию. Обратите внимание: обратное неверно — передача этого параметра конструктору не добавит модель в коллекцию автоматически. Иногда это полезно.

Если передать {parse: true} в качестве параметра, атрибуты сначала будут преобразованы с помощью parse, а затем установлены для модели.

getmodel.get(attribute)
Получить текущее значение атрибута модели. Например: note.get("title")

setmodel.set(attributes, [options])
Установить для модели набор атрибутов — один или несколько. Если какие-либо атрибуты изменят состояние модели, для неё будет вызвано событие "change". Также вызываются события изменения конкретных атрибутов, на которые тоже можно подписаться, например: change:title и change:content. Можно также передавать отдельные ключи и значения.

note.set({title: "March 20", content: "In his eyes she eclipses..."});

book.set("title", "A Scandal in Bohemia");

escapemodel.escape(attribute)
Аналогично get, но возвращает HTML-экранированную версию атрибута модели. Если вы вставляете данные модели в HTML, получение атрибутов с помощью escape поможет предотвратить атаки XSS.

var hacker = new Backbone.Model({
  name: "<script>alert('xss')</script>"
});

alert(hacker.escape('name'));

hasmodel.has(attribute)
Возвращает true, если атрибут задан и имеет значение, отличное от null или undefined.

if (note.has("title")) {
  ...
}

unsetmodel.unset(attribute, [options])
Удалить атрибут, удалив его из внутреннего хранилища атрибутов. Вызывает событие "change", если в качестве параметра не передан silent.

clearmodel.clear([options])
Удаляет все атрибуты модели, в том числе атрибут id. Вызывает событие "change", если в качестве параметра не передан silent.

idmodel.id
Специальное свойство моделей: id — это произвольная строка (целочисленный идентификатор или UUID). Если задать id в наборе атрибутов, он будет скопирован в модель как прямое свойство. model.id не следует изменять напрямую — это можно делать только с помощью model.set('id', …). Модели можно получать из коллекций по идентификатору; по умолчанию он используется для формирования URL моделей.

idAttributemodel.idAttribute
Уникальный идентификатор модели хранится в атрибуте id. Если вы напрямую взаимодействуете с серверной частью (CouchDB, MongoDB), где используется другой уникальный ключ, можно задать для модели idAttribute, чтобы прозрачно сопоставить этот ключ с id. Если вы задаёте idAttribute, возможно, потребуется также переопределить cidPrefix.

var Meal = Backbone.Model.extend({
  idAttribute: "_id"
});

var cake = new Meal({ _id: 1, name: "Cake" });
alert("Cake id: " + cake.id);

cidmodel.cid
Специальное свойство моделей: cid, или клиентский идентификатор, — это уникальный идентификатор, автоматически назначаемый каждой модели при её создании. Клиентские идентификаторы полезны, когда модель ещё не сохранена на сервере и у неё пока нет окончательного id, но её уже нужно отображать в интерфейсе.

cidPrefixmodel.cidPrefix
Если id модели имеет значение, отличное от целого числа или UUID, оно может совпасть с cid. Чтобы этого избежать, можно переопределить префикс, с которого начинаются cid.

// If both lengths are 2, refresh the page before running this example.
var clashy = new Backbone.Collection([
  {id: 'c2'},
  {id: 'c1'},
]);
alert('clashy length: ' + clashy.length);

var ClashFree = Backbone.Model.extend({cidPrefix: 'm'});
var clashless = new Backbone.Collection([
  {id: 'c3'},
  {id: 'c2'},
], {model: ClashFree});
alert('clashless length: ' + clashless.length);

attributesmodel.attributes
Свойство attributes — это внутреннее хранилище, содержащее состояние модели: обычно (но не обязательно) оно представляет собой объект JSON с данными модели на сервере. Часто это простая сериализация строки базы данных, но здесь также могут храниться вычисляемые на стороне клиента данные.

Для обновления attributes используйте set, а не изменяйте их напрямую. Чтобы получить и преобразовать копию атрибутов модели, используйте _.clone(model.attributes).

Поскольку Events поддерживает разделённые пробелами списки событий, имена атрибутов не должны содержать пробелы.

changedmodel.changed
Свойство changed — это внутреннее хранилище, содержащее все атрибуты, изменившиеся после последнего вызова set. Не обновляйте changed напрямую, поскольку его состояние внутренне поддерживается методом set. Копию changed можно получить с помощью changedAttributes.

defaultsmodel.defaults or model.defaults()
Хеш-объект (или функция) defaults позволяет задать атрибуты модели по умолчанию. При создании экземпляра модели всем неуказанным атрибутам присваиваются значения по умолчанию.

var Meal = Backbone.Model.extend({
  defaults: {
    "appetizer":  "caesar salad",
    "entree":     "ravioli",
    "dessert":    "cheesecake"
  }
});

alert("Dessert will be " + (new Meal).get('dessert'));

Помните, что в JavaScript объекты передаются по ссылке. Поэтому, если включить объект в качестве значения по умолчанию, он будет общим для всех экземпляров. Вместо этого определите defaults как функцию.

Если для idAttribute модели задано значение, следует определить defaults как функцию, возвращающую новый, глобально уникальный идентификатор при каждом вызове. Иначе экземпляр Backbone.Collection, скорее всего, не сможет правильно идентифицировать хеши моделей. Это почти наверняка ошибка, если только вы никогда не добавляете экземпляры класса модели в коллекцию.

toJSONmodel.toJSON([options])
Возвращает поверхностную копию атрибутов модели для преобразования в строку JSON. Это можно использовать для сохранения, сериализации или дополнения данных перед отправкой на сервер. Название этого метода может сбивать с толку: он не возвращает строку JSON. Но, к сожалению, именно так работает API JavaScript для JSON.stringify.

var artist = new Backbone.Model({
  firstName: "Wassily",
  lastName: "Kandinsky"
});

artist.set({birthday: "December 16, 1866"});

alert(JSON.stringify(artist));

syncmodel.sync(method, model, [options])
Использует Backbone.sync для сохранения состояния модели на сервере. Можно переопределить для настройки поведения.

fetchmodel.fetch([options])
Объединяет состояние модели с атрибутами, полученными с сервера, делегируя задачу Backbone.sync. Возвращает объект jqXHR. Полезен, если модель ещё не была заполнена данными или если нужно убедиться, что у вас есть актуальное состояние сервера. Вызывает событие "change", если состояние сервера отличается от текущих атрибутов. fetch принимает функции обратного вызова success и error в хеше параметров; обеим передаются аргументы (model, response, options).

// Poll every 10 seconds to keep the channel model up-to-date.
setInterval(function() {
  channel.fetch();
}, 10000);

savemodel.save([attributes], [options])
Сохраняет модель в базе данных (или другом хранилище), делегируя задачу Backbone.sync. Возвращает объект jqXHR, если проверка прошла успешно, и false в противном случае. Хеш attributes (как и в set) должен содержать атрибуты, которые нужно изменить: неуказанные ключи останутся без изменений, но на сервер будет отправлено полное представление ресурса. Как и в set, вместо хеша можно передать отдельные ключи и значения. Если у модели есть метод validate и проверка завершается неудачей, модель не будет сохранена. Если модель новая, сохранение будет выполнено методом "create" (HTTP POST); если модель уже существует на сервере, сохранение будет выполнено методом "update" (HTTP PUT).

Если нужно отправить на сервер только изменённые атрибуты, вызовите model.save(attrs, {patch: true}). На сервер будет отправлен HTTP-запрос PATCH только с переданными атрибутами.

Вызов save с новыми атрибутами немедленно вызовет событие "change", затем событие "request" при отправке Ajax-запроса на сервер и событие "sync" после подтверждения сервером успешного изменения. Передайте {wait: true}, если нужно дождаться ответа сервера, прежде чем задавать модели новые атрибуты.

В следующем примере обратите внимание: переопределённая версия Backbone.sync получает запрос "create" при первом сохранении модели и запрос "update" при втором.

Backbone.sync = function(method, model) {
  alert(method + ": " + JSON.stringify(model));
  model.set('id', 1);
};

var book = new Backbone.Model({
  title: "The Rough Riders",
  author: "Theodore Roosevelt"
});

book.save();

book.save({author: "Teddy"});

save принимает функции обратного вызова success и error в хеше параметров; им будут переданы аргументы (model, response, options). Если проверка на стороне сервера завершается неудачей, верните отличный от 200 код ответа HTTP, а также сообщение об ошибке в текстовом формате или JSON.

book.save("author", "F.D.R.", {error: function(){ ... }});

destroymodel.destroy([options])
Уничтожает модель на сервере, делегируя Backbone.sync HTTP-запрос DELETE. Возвращает объект jqXHR или false, если модель новая. Принимает функции обратного вызова success и error в хеше параметров; им передаются аргументы (model, response, options). Вызывает событие "destroy" для модели, которое распространяется на все содержащие её коллекции, событие "request" при отправке Ajax-запроса на сервер и событие "sync" после того, как сервер подтвердит удаление модели. Передайте {wait: true}, если нужно дождаться ответа сервера, прежде чем удалять модель из коллекции.

book.destroy({success: function(model, response) {
  ...
}});

Методы Underscore (9)
Backbone предоставляет через Underscore.js 9 функций для объектов в Backbone.Model. Здесь описаны не все из них, но подробную информацию можно найти в документации Underscore…

  • keys
  • values
  • pairs
  • invert
  • pick
  • omit
  • chain
  • isEmpty
user.pick('first_name', 'last_name', 'email');

chapters.keys().join(', ');

validatemodel.validate(attributes, options)
Этот метод не определён; рекомендуется переопределить его, реализовав собственную логику проверки, которую можно выполнить в JavaScript. Если атрибуты допустимы, метод validate не должен ничего возвращать; если они недопустимы, верните ошибку по своему выбору. Это может быть простое текстовое сообщение об ошибке или полноценный объект ошибки с программным описанием.

По умолчанию save проверяет validate перед установкой любых атрибутов, но можно также попросить set проверить новые атрибуты, передав {validate: true} в качестве параметра. Метод validate получает атрибуты модели и любые параметры, переданные в set или save. Если validate возвращает ошибку, save не продолжает работу, атрибуты модели не изменяются на сервере, вызывается событие "invalid", а свойству validationError модели присваивается возвращённое этим методом значение.

var Chapter = Backbone.Model.extend({
  validate: function(attrs, options) {
    if (attrs.end < attrs.start) {
      return "can't end before it starts";
    }
  }
});

var one = new Chapter({
  title : "Chapter One: The Beginning"
});

one.on("invalid", function(model, error) {
  alert(model.get("title") + " " + error);
});

one.save({
  start: 15,
  end:   10
});

События "invalid" полезны для предоставления обобщённых сообщений об ошибках на уровне модели или коллекции.

validationErrormodel.validationError
Значение, возвращённое методом validate при последней неудачной проверке.

isValidmodel.isValid(options)
Запускает validate для проверки состояния модели.

Метод validate получает атрибуты модели и любые параметры, переданные в isValid. Если validate возвращает ошибку, вызывается событие "invalid", а ошибка сохраняется в свойстве validationError модели.

var Chapter = Backbone.Model.extend({
  validate: function(attrs, options) {
    if (attrs.end < attrs.start) {
      return "can't end before it starts";
    }
  }
});

var one = new Chapter({
  title : "Chapter One: The Beginning"
});

one.set({
  start: 15,
  end:   10
});

if (!one.isValid()) {
  alert(one.get("title") + " " + one.validationError);
}

urlmodel.url()
Возвращает относительный URL ресурса модели на сервере. Если модели хранятся в другом месте, переопределите этот метод, указав правильную логику. По умолчанию формируются URL вида: "[collection.url]/[id]", но можно переопределить их, указав явный urlRoot, если при формировании URL не нужно учитывать коллекцию модели.

Для формирования URL делегирует вызов Collection#url, поэтому убедитесь, что он определён, либо задано свойство urlRoot, если у всех моделей этого класса общий корневой URL. Модель с идентификатором 101, хранящаяся в Backbone.Collection со значением url, равным "/documents/7/notes", будет иметь следующий URL: "/documents/7/notes/101"

urlRootmodel.urlRoot or model.urlRoot()
Укажите urlRoot, если используете модель вне коллекции, чтобы стандартная функция url могла формировать URL на основе идентификатора модели. "[urlRoot]/id"
Обычно это свойство не нужно определять. Обратите внимание, что urlRoot также может быть функцией.

var Book = Backbone.Model.extend({urlRoot : '/books'});

var solaris = new Book({id: "1083-lem-solaris"});

alert(solaris.url());

parsemodel.parse(response, options)
Метод parse вызывается каждый раз, когда сервер возвращает данные модели в методах fetch и save. Функция получает исходный объект response и должна вернуть хеш атрибутов, который будет установлен для модели. Стандартная реализация ничего не делает и просто передаёт ответ JSON. Переопределите её, если нужно работать с существующим API или лучше организовать пространство имён ответов.

Если вы используете серверную часть на Rails версии ниже 3.1, обратите внимание: стандартная реализация to_json помещает атрибуты модели в пространство имён. Чтобы отключить это поведение для бесшовной интеграции с Backbone, задайте:

ActiveRecord::Base.include_root_in_json = false

clonemodel.clone()
Возвращает новый экземпляр модели с идентичными атрибутами.

isNewmodel.isNew()
Была ли эта модель сохранена на сервере? Если у модели ещё нет id, она считается новой.

hasChangedmodel.hasChanged([attribute])
Изменилась ли модель после последнего вызова set? Если передан атрибут, возвращает true, если изменился именно этот атрибут.

Обратите внимание: этот метод, как и следующие методы, связанные с изменениями, полезен только во время события "change".

book.on("change", function() {
  if (book.hasChanged("title")) {
    ...
  }
});

changedAttributesmodel.changedAttributes([attributes])
Получить хеш только тех атрибутов модели, которые изменились после последнего вызова set, или false, если таких атрибутов нет. Можно передать внешний хеш attributes; метод вернёт атрибуты из этого хеша, отличающиеся от атрибутов модели. Это можно использовать, чтобы определить, какие части представления нужно обновить или какие вызовы нужны для синхронизации изменений с сервером.

previousmodel.previous(attribute)
Во время события "change" этот метод можно использовать для получения предыдущего значения изменённого атрибута.

var bill = new Backbone.Model({
  name: "Bill Smith"
});

bill.on("change:name", function(model, name) {
  alert("Changed name from " + bill.previous("name") + " to " + name);
});

bill.set({name : "Bill Jones"});

previousAttributesmodel.previousAttributes()
Возвращает копию предыдущих атрибутов модели. Полезно для сравнения версий модели или возврата к допустимому состоянию после возникновения ошибки.

Backbone.Collection

Коллекции — это упорядоченные наборы моделей. Можно привязывать события "change", чтобы получать уведомления об изменении любой модели в коллекции, прослушивать события "add" и "remove", fetch коллекцию с сервера и использовать полный набор методов Underscore.js.

Любое событие, вызванное для модели в коллекции, также будет вызвано непосредственно для коллекции — для удобства. Это позволяет, например, прослушивать изменения определённых атрибутов в любой модели коллекции: documents.on("change:selected", ...)

extendBackbone.Collection.extend(properties, [classProperties])
Чтобы создать собственный класс Collection, расширьте Backbone.Collection, указав свойства экземпляра (properties), а также необязательные свойства класса (classProperties), которые будут добавлены непосредственно к функции-конструктору коллекции.

modelcollection.model([attrs], [options])
Переопределите это свойство, чтобы указать класс моделей, содержащихся в коллекции. Если свойство определено, в методы add, create и reset можно передавать объекты исходных атрибутов (и массивы) и параметры; атрибуты будут преобразованы в модель нужного типа с использованием переданных параметров, если они есть.

var Library = Backbone.Collection.extend({
  model: Book
});

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

var Library = Backbone.Collection.extend({

  model: function(attrs, options) {
    if (condition) {
      return new PublicDocument(attrs, options);
    } else {
      return new PrivateDocument(attrs, options);
    }
  }

});

modelIdcollection.modelId(attrs, idAttribute)
Переопределите этот метод, чтобы вернуть значение, которое коллекция будет использовать для идентификации модели по её атрибутам. Полезно при объединении в одной коллекции моделей из нескольких таблиц с разными значениями idAttribute.

По умолчанию возвращает значение указанного idAttribute в attrs или, если оно отсутствует, id. Если коллекция использует фабрику моделей и диапазоны идентификаторов этих моделей могут совпадать, необходимо переопределить этот метод.

var Library = Backbone.Collection.extend({
  modelId: function(attrs) {
    return attrs.type + attrs.id;
  }
});

var library = new Library([
  {type: 'dvd', id: 1},
  {type: 'vhs', id: 1}
]);

var dvdId = library.get('dvd1').id;
var vhsId = library.get('vhs1').id;
alert('dvd: ' + dvdId + ', vhs: ' + vhsId);

preinitializenew Backbone.Collection([models], [options])
Используется с коллекциями в виде классов ES. Если определить метод preinitialize, он будет вызван при создании коллекции, до выполнения логики её инициализации.

class Library extends Backbone.Collection {
  preinitialize() {
    this.on("add", function() {
      console.log("Add model event got fired!");
    });
  }
}

constructor / initializenew Backbone.Collection([models], [options])
При создании коллекции можно передать исходный массив моделей. В качестве параметра можно указать компаратор коллекции. Передача false в качестве параметра компаратора отключит сортировку. Если определить функцию initialize, она будет вызвана при создании коллекции. Некоторые параметры при передаче напрямую добавляются к коллекции: model и comparator.
Передайте null для models, чтобы создать пустую коллекцию с options.

var tabs = new TabSet([tab1, tab2, tab3]);
var spaces = new Backbone.Collection(null, {
  model: Space
});

Если {parse: true} передан как option, перед установкой attributes в коллекцию они будут преобразованы с помощью parse.

modelscollection.models
Прямой доступ к массиву JavaScript с моделями внутри коллекции. Обычно для доступа к объектам моделей следует использовать get, at или методы Underscore, но иногда требуется получить прямую ссылку на массив.

toJSONcollection.toJSON([options])
Возвращает массив, содержащий хэш атрибутов каждой модели (через toJSON) в коллекции. Это можно использовать для сериализации и сохранения коллекции целиком. Название этого метода немного сбивает с толку, поскольку оно соответствует API JSON в JavaScript.

var collection = new Backbone.Collection([
  {name: "Tim", age: 5},
  {name: "Ida", age: 26},
  {name: "Rob", age: 55}
]);

alert(JSON.stringify(collection));

synccollection.sync(method, collection, [options])
Использует Backbone.sync для сохранения состояния коллекции на сервере. Можно переопределить для настройки поведения.

Методы Underscore (46)
Backbone предоставляет через Underscore.js 46 функций итерации для Backbone.Collection. Здесь описаны не все из них, но полную информацию можно найти в документации Underscore…

Большинство методов могут принимать объект или строку для поддержки предикатов в стиле атрибутов модели либо функцию, получающую экземпляр модели в качестве аргумента.

  • forEach (each)
  • map (collect)
  • reduce (foldl, inject)
  • reduceRight (foldr)
  • find (detect)
  • findIndex
  • findLastIndex
  • filter (select)
  • reject
  • every (all)
  • some (any)
  • contains (includes)
  • invoke
  • max
  • min
  • sortBy
  • groupBy
  • shuffle
  • toArray
  • size
  • first (head, take)
  • initial
  • rest (tail, drop)
  • last
  • without
  • indexOf
  • lastIndexOf
  • isEmpty
  • chain
  • difference
  • sample
  • partition
  • countBy
  • indexBy
books.each(function(book) {
  book.publish();
});

var titles = books.map("title");

var publishedBooks = books.filter({published: true});

var alphabetical = books.sortBy(function(book) {
  return book.author.get("name").toLowerCase();
});

var randomThree = books.sample(3);

addcollection.add(models, [options])
Добавляет модель (или массив моделей) в коллекцию, вызывая событие "add" для каждой модели, а затем событие "update". Это вариант метода set с теми же параметрами и возвращаемым значением, но он всегда добавляет модели и никогда их не удаляет. Если добавляемые модели уже есть в коллекции, они будут проигнорированы, если не передать {merge: true}; в этом случае их атрибуты будут объединены с атрибутами соответствующих моделей, и будут вызваны все необходимые события "change".

var ships = new Backbone.Collection;

ships.on("add", function(ship) {
  alert("Ahoy " + ship.get("name") + "!");
});

ships.add([
  {name: "Flying Dutchman"},
  {name: "Black Pearl"}
]);

Обратите внимание: повторное добавление одной и той же модели (модели с тем же id) в коллекцию
ничего не меняет.

removecollection.remove(models, [options])
Удаляет модель (или массив моделей) из коллекции и возвращает их. Каждая модель может быть экземпляром Model, строкой id или объектом JS — любым значением, допустимым в качестве аргумента id метода collection.get. Для каждой модели вызывается событие "remove", а затем однократно событие "update", если не передан параметр {silent: true}. Индекс модели до удаления доступен обработчикам событий через options.index.

resetcollection.reset([models], [options])
Добавление и удаление моделей по одной — вполне подходящий способ, но иногда моделей для изменения так много, что удобнее обновить коллекцию целиком. Используйте reset, чтобы заменить коллекцию новым списком моделей (или хэшей атрибутов), вызвав по завершении одно событие "reset" и не вызывая события добавления или удаления для отдельных моделей. Возвращает модели, установленные в коллекцию. Для удобства в обработчике события "reset" список предыдущих моделей доступен через options.previousModels.
Передайте null в качестве models, чтобы очистить коллекцию с помощью options.

Вот пример использования reset для заполнения коллекции при первоначальной загрузке страницы в приложении Rails:

<script>
  var accounts = new Backbone.Collection;
  accounts.reset(<%= @accounts.to_json %>);
</script>

Вызов collection.reset() без передачи моделей в качестве аргументов очистит всю коллекцию.

setcollection.set(models, [options])
Метод set выполняет «интеллектуальное» обновление коллекции переданным списком моделей. Если модели из списка ещё нет в коллекции, она будет добавлена; если модель уже есть, её атрибуты будут объединены; а модели, имеющиеся в коллекции, но отсутствующие в списке, будут удалены. При этом вызываются все соответствующие события "add", "remove" и "change", а в конце — одно событие "update". Возвращает затронутые модели в коллекции. Чтобы настроить это поведение, используйте параметры {add: false}, {remove: false} или {merge: false}.

Если задано свойство model, можно также передать обычные объекты атрибутов и параметры, чтобы на их основе создать экземпляры модели с использованием переданных параметров. Если задан comparator, коллекция автоматически отсортируется и вызовет событие "sort", если не передать {sort: false} или не использовать параметр {at: index}. Передайте {at: index}, чтобы вставить модель (модели) в коллекцию по указанному индексу index.

var vanHalen = new Backbone.Collection([eddie, alex, stone, roth]);

vanHalen.set([eddie, alex, stone, hagar]);

// Fires a "remove" event for roth, and an "add" event for "hagar".
// Updates any of stone, alex, and eddie's attributes that may have
// changed over the years.

getcollection.get(id)
Получает модель из коллекции, указанную по id, cid или переданную в виде model.

var book = library.get(110);

atcollection.at(index)
Получает модель из коллекции по индексу. Полезно, если коллекция отсортирована; если же она не отсортирована, at всё равно возвращает модели в порядке их добавления. При передаче отрицательного индекса модель будет получена с конца коллекции.

pushcollection.push(model, [options])
Подобно add, но всегда добавляет модель в конец коллекции и никогда не сортирует её.

popcollection.pop([options])
Удаляет и возвращает последнюю модель из коллекции. Принимает те же параметры, что и remove.

unshiftcollection.unshift(model, [options])
Подобно add, но всегда добавляет модель в начало коллекции и никогда не сортирует её.

shiftcollection.shift([options])
Удаляет и возвращает первую модель из коллекции. Принимает те же параметры, что и remove.

slicecollection.slice(begin, end)
Возвращает поверхностную копию моделей этой коллекции, используя те же параметры, что и встроенный метод Array#slice.

lengthcollection.length
Как и массив, Collection содержит свойство length, которое показывает количество моделей в ней.

comparatorcollection.comparator
По умолчанию у коллекции нет comparator. Если определить comparator, он будет использоваться для сортировки коллекции при добавлении каждой модели. Comparator можно задать как sortBy (передав функцию, принимающую один аргумент), как sort (передав функцию сравнения, принимающую два аргумента) или как строку, указывающую атрибут для сортировки.

Функции сравнения «sortBy» принимают модель и возвращают числовое или строковое значение, определяющее её порядок относительно остальных моделей. Функции сравнения «sort» принимают две модели и возвращают -1, если первая модель должна располагаться перед второй, 0, если они имеют одинаковый ранг, и 1, если первая модель должна располагаться после второй. Обратите внимание: Backbone определяет тип вашей функции сравнения по её арности, поэтому соблюдайте осторожность, если функция связана с контекстом.

Обратите внимание: хотя в этом примере все главы добавляются в обратном порядке, в итоге они расположены правильно:

var Chapter  = Backbone.Model;
var chapters = new Backbone.Collection;

chapters.comparator = 'page';

chapters.add(new Chapter({page: 9, title: "The End"}));
chapters.add(new Chapter({page: 5, title: "The Middle"}));
chapters.add(new Chapter({page: 1, title: "The Beginning"}));

alert(chapters.pluck('title'));

Коллекции с comparator не будут автоматически сортироваться повторно, если впоследствии изменить атрибуты модели. Поэтому после изменения атрибутов, влияющих на порядок, может потребоваться вызвать sort.

sortcollection.sort([options])
Принудительно выполняет повторную сортировку коллекции. Обратите внимание: коллекция с comparator сортируется автоматически при добавлении каждой модели. Чтобы отключить сортировку при добавлении модели, передайте {sort: false} в add. Вызов sort вызывает событие "sort" в коллекции.

pluckcollection.pluck(attribute)
Извлекает атрибут из каждой модели коллекции. Эквивалентно вызову map с возвратом одного атрибута из итератора.

var stooges = new Backbone.Collection([
  {name: "Curly"},
  {name: "Larry"},
  {name: "Moe"}
]);

var names = stooges.pluck("name");

alert(JSON.stringify(names));

wherecollection.where(attributes)
Возвращает массив всех моделей коллекции, соответствующих переданным attributes. Полезно для простых случаев filter.

var friends = new Backbone.Collection([
  {name: "Athos",      job: "Musketeer"},
  {name: "Porthos",    job: "Musketeer"},
  {name: "Aramis",     job: "Musketeer"},
  {name: "d'Artagnan", job: "Guard"},
]);

var musketeers = friends.where({job: "Musketeer"});

alert(musketeers.length);

findWherecollection.findWhere(attributes)
Подобно where, но возвращает непосредственно только первую модель коллекции, соответствующую переданным attributes. Если подходящих моделей нет, возвращает undefined.

urlcollection.url or collection.url()
Задайте свойство (или функцию) url коллекции, чтобы указать её расположение на сервере. Модели коллекции будут использовать url для построения собственных URL.

var Notes = Backbone.Collection.extend({
  url: '/notes'
});

// Or, something more sophisticated:

var Notes = Backbone.Collection.extend({
  url: function() {
    return this.document.url() + '/notes';
  }
});

parsecollection.parse(response, options)
Backbone вызывает parse, когда сервер возвращает модели коллекции в ответ на fetch. Функция получает исходный объект response и должна вернуть массив атрибутов моделей, которые будут добавлены в коллекцию. Реализация по умолчанию ничего не делает, просто передавая ответ JSON дальше. Переопределите её, если нужно работать с уже существующим API или лучше структурировать ответы с помощью пространств имён.

var Tweets = Backbone.Collection.extend({
  // The Twitter Search API returns tweets under "results".
  parse: function(response) {
    return response.results;
  }
});

clonecollection.clone()
Возвращает новый экземпляр коллекции с таким же списком моделей.

fetchcollection.fetch([options])
Загружает с сервера стандартный набор моделей для этой коллекции и устанавливает их в коллекцию после получения. Хэш options принимает обратные вызовы success и error; оба получают (collection, response, options) в качестве аргументов. После получения данных моделей с сервера метод использует set для (интеллектуального) объединения загруженных моделей, если только не передан параметр {reset: true} — в этом случае коллекция будет (эффективно) сброшена. Для пользовательских стратегий сохранения внутри делегирует вызов Backbone.sync и возвращает jqXHR. Обработчик запроса fetch на сервере должен возвращать массив моделей в формате JSON.

Backbone.sync = function(method, model) {
  alert(method + ": " + model.url);
};

var accounts = new Backbone.Collection;
accounts.url = '/accounts';

accounts.fetch();

Поведение fetch можно настроить с помощью доступных параметров set. Например, чтобы загрузить коллекцию, получая событие "add" для каждой новой модели и событие "change" для каждой изменённой существующей модели, ничего не удаляя: collection.fetch({remove: false})

Параметры jQuery.ajax также можно передавать непосредственно в качестве параметров fetch. Например, чтобы загрузить определённую страницу постранично разбитой коллекции: Documents.fetch({data: {page: 3}})

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

createcollection.create(attributes, [options])
Вспомогательный метод для создания нового экземпляра модели внутри коллекции. Эквивалентен созданию экземпляра модели с хэшем атрибутов, сохранению модели на сервере и добавлению её в набор после успешного создания. Возвращает новую модель. Если проверка на стороне клиента завершилась неудачей, модель не будет сохранена и будет содержать ошибки проверки. Для работы этого метода необходимо задать свойство коллекции model. Метод create принимает хэш атрибутов и параметры, передаваемые при создании модели, либо существующий несохранённый объект модели.

Создание модели немедленно вызывает событие "add" в коллекции, событие "request" при отправке новой модели на сервер, а также событие "sync" после того, как сервер подтвердит успешное создание модели. Передайте {wait: true}, если нужно дождаться ответа сервера, прежде чем добавлять новую модель в коллекцию.

var Library = Backbone.Collection.extend({
  model: Book
});

var nypl = new Library;

var othello = nypl.create({
  title: "Othello",
  author: "William Shakespeare"
});

mixinBackbone.Collection.mixin(properties)
mixin предоставляет способ расширить базовый класс Backbone.Collection и любые коллекции, производные от него. Это можно использовать для добавления универсальных методов (например, дополнительных методов Underscore).

Backbone.Collection.mixin({
  sum: function(models, iteratee) {
    return _.reduce(models, function(s, m) {
      return s + iteratee(m);
    }, 0);
  }
});

var cart = new Backbone.Collection([
  {price: 16, name: 'monopoly'},
  {price: 5, name: 'deck of cards'},
  {price: 20, name: 'chess'}
]);

var cost = cart.sum('price');

Backbone.Router

Веб-приложения часто предоставляют URL-адреса для важных разделов приложения, которыми можно делиться, добавлять их в закладки и открывать по ссылке. До недавнего времени для создания таких постоянных ссылок использовались фрагменты хэша (#page), но с появлением History API стало возможно использовать обычные URL-адреса (/page). Backbone.Router предоставляет методы для маршрутизации страниц на стороне клиента и их связывания с действиями и событиями. В браузерах, которые ещё не поддерживают History API, Router обеспечивает корректный запасной вариант и прозрачное преобразование URL в версию с фрагментом.

Во время загрузки страницы, после создания всех маршрутизаторов приложения, обязательно вызовите Backbone.history.start() или Backbone.history.start({pushState: true}), чтобы обработать исходный URL.

extendBackbone.Router.extend(properties, [classProperties])
Для начала создайте собственный класс маршрутизатора. Определите функции-действия, вызываемые при совпадении с определёнными фрагментами URL, и задайте хэш routes, связывающий маршруты с действиями. Обратите внимание: в определениях маршрутов не следует использовать начальный слеш:

var Workspace = Backbone.Router.extend({

  routes: {
    "help":                 "help",    // #help
    "search/:query":        "search",  // #search/kiwis
    "search/:query/p:page": "search"   // #search/kiwis/p7
  },

  help: function() {
    ...
  },

  search: function(query, page) {
    ...
  }

});

routesrouter.routes
Хэш routes сопоставляет URL-адреса с параметрами функциям маршрутизатора (или непосредственно определениям функций, если вы предпочитаете такой способ), подобно хэшу events у View. Маршруты могут содержать части-параметры :param, соответствующие одному компоненту URL между слешами, и части-шаблоны *splat, которые могут соответствовать любому количеству компонентов URL. Часть маршрута можно сделать необязательной, заключив её в круглые скобки (/:optional).

Например, маршрут "search/:query/p:page" будет соответствовать фрагменту #search/obama/p2, передавая "obama" и "2" действию в качестве позиционных аргументов.

Маршрут "file/*path" будет соответствовать #file/folder/file.txt, передавая "folder/file.txt" действию.

Маршрут "docs/:section(/:subsection)" будет соответствовать #docs/faq и #docs/faq/installing: в первом случае действию будет передан "faq", а во втором — "faq" и "installing".

Маршрут с вложенными необязательными частями "docs(/:section)(/:subsection)" будет соответствовать #docs, #docs/faq и #docs/faq/installing; во втором случае действию будет передан "faq", а в третьем — "faq" и "installing".

Завершающие слеши считаются частью URL и (что правильно) при обращении рассматриваются как отдельный маршрут. docs и docs/ вызовут разные обратные вызовы. Если избежать создания URL обоих типов невозможно, можно определить сопоставитель "docs(/)", учитывающий оба случая.

Когда посетитель нажимает кнопку «Назад» или вводит URL и находится соответствующий маршрут, имя действия вызывается как событие, чтобы другие объекты могли прослушивать маршрутизатор и получать уведомления. В следующем примере при посещении #help/uploading маршрутизатор вызовет событие route:help.

routes: {
  "help/:page":         "help",
  "download/*path":     "download",
  "folder/:name":       "openFolder",
  "folder/:name-:mode": "openFolder"
}
router.on("route:help", function(page) {
  ...
});

preinitializenew Backbone.Router([options])
Используется с маршрутизаторами в виде классов ES. Если определить метод preinitialize, он будет вызван при первоначальном создании Router, до выполнения какой-либо логики его создания.

class Router extends Backbone.Router {
  preinitialize() {
    // Override execute method
    this.execute = function(callback, args, name) {
      if (!loggedIn) {
        goToLogin();
        return false;
      }
      args.push(parseQueryString(args.pop()));
      if (callback) callback.apply(this, args);
    }
  }
}

constructor / initializenew Router([options])
При создании маршрутизатора при желании можно передать хэш routes непосредственно как параметр. Все options также будут переданы вашей функции initialize, если она определена.

routerouter.route(route, name, [callback])
Вручную создаёт маршрут для маршрутизатора. Аргумент route может быть строкой маршрута или регулярным выражением. Каждое совпадение с захватывающей группой маршрута или регулярного выражения будет передано обратному вызову как аргумент. Аргумент name будет вызван как событие "route:name" при каждом совпадении с маршрутом. Если аргумент callback не указан, вместо него будет использоваться router[name]. Маршруты, добавленные позднее, могут переопределять ранее объявленные маршруты.

initialize: function(options) {

  // Matches #page/10, passing "10"
  this.route("page/:number", "page", function(number){ ... });

  // Matches /117-a/b/c/open, passing "117-a/b/c" to this.open
  this.route(/^(.*?)\/open$/, "open");

},

open: function(id) { ... }

navigaterouter.navigate(fragment, [options])
Когда в приложении вы достигаете точки, которую нужно сохранить как URL, вызовите navigate, чтобы обновить URL. Если также требуется вызвать функцию маршрута, задайте для параметра trigger значение true. Чтобы обновить URL, не создавая запись в истории браузера, задайте для параметра replace значение true.

openPage: function(pageNumber) {
  this.document.pages.at(pageNumber).open();
  this.navigate("page/" + pageNumber);
}

# Or ...

app.navigate("help/troubleshooting", {trigger: true});

# Or ...

app.navigate("help/troubleshooting", {trigger: true, replace: true});

executerouter.execute(callback, args, name)
Этот метод вызывается внутри маршрутизатора при совпадении маршрута, непосредственно перед выполнением соответствующего callback. Верните из execute значение false, чтобы отменить текущий переход. Переопределите метод, чтобы настроить разбор или обёртывание маршрутов; например, чтобы разобрать строки запроса до их передачи обратному вызову маршрута:

var Router = Backbone.Router.extend({
  execute: function(callback, args, name) {
    if (!loggedIn) {
      goToLogin();
      return false;
    }
    args.push(parseQueryString(args.pop()));
    if (callback) callback.apply(this, args);
  }
});

Backbone.history

History служит глобальным маршрутизатором (для каждого фрейма) для обработки событий hashchange или pushState, сопоставления соответствующего маршрута и вызова обратных вызовов. Он передаёт события "route" и "route[name]" подходящего маршрутизатора либо "notfound", если текущему URL не соответствует ни один маршрут ни в одном маршрутизаторе. Вам не придётся создавать его самостоятельно, поскольку Backbone.history уже содержит экземпляр History.

Поддержка pushState в Backbone включается только по желанию. Старые браузеры, не поддерживающие pushState, продолжат использовать фрагменты URL с хэшем, а если браузер с поддержкой pushState откроет URL с хэшем, он будет прозрачно преобразован в настоящий URL. Обратите внимание: для использования настоящих URL веб-сервер должен уметь правильно отображать соответствующие страницы, поэтому потребуется внести изменения на стороне сервера. Например, если у вас есть маршрут /documents/100, веб-сервер должен уметь отдать эту страницу при прямом переходе браузера по такому URL. Для полной доступности для поисковых роботов лучше, чтобы сервер создавал полный HTML-код страницы… но для веб-приложения вполне достаточно, чтобы он отображал то же содержимое, что и для корневого URL, а остальная часть формировалась с помощью Backbone Views и JavaScript.

startBackbone.history.start([options])
После создания всех маршрутизаторов и правильной настройки маршрутов вызовите Backbone.history.start(), чтобы начать отслеживание событий hashchange и обработку маршрутов. Повторные вызовы Backbone.history.start() приведут к ошибке, а Backbone.History.started — это логическое значение, указывающее, был ли метод уже вызван.

Чтобы указать, что приложение должно использовать поддержку HTML5 pushState, передайте Backbone.history.start({pushState: true}). Если вы хотите использовать pushState, но при этом заставить браузеры без встроенной поддержки выполнять полную перезагрузку страницы, добавьте в параметры {hashChange: false}.

Если приложение размещено не в корневом URL / вашего домена, обязательно укажите в History настоящий корневой URL в качестве параметра: Backbone.history.start({pushState: true, root: "/public/search/"}).

Значение, заданное для root, будет нормализовано: в начало и конец будет добавлен слеш. При переходе к маршруту по умолчанию завершающий слеш исключается из URL (например, /public/search?query=...). Чтобы включить завершающий слеш (например, /public/search/?query=...), используйте Backbone.history.start({trailingSlash: true}). В URL всегда будет присутствовать начальный слеш. Если корень — /, URL будут выглядеть как /?query=... независимо от значения trailingSlash.

При вызове, если текущему URL соответствует маршрут, Backbone.history.start() возвращает true и вызываются события "route" и "route[name]". Если текущему URL не соответствует ни один определённый маршрут, метод возвращает false и вместо этого вызывается "notfound".

Если сервер уже отобразил всю страницу и при запуске History не нужно вызывать исходный маршрут, передайте silent: true.

Поскольку история на основе хэша в Internet Explorer использует <iframe>, обязательно вызывайте start() только после готовности DOM.

$(function(){
  new WorkspaceRouter();
  new HelpPaneRouter();
  Backbone.history.start({pushState: true});
});

Backbone.sync

Backbone.sync — это функция, которую Backbone вызывает при каждой попытке прочитать модель с сервера или сохранить её на сервере. По умолчанию для RESTful-запросов JSON она использует jQuery.ajax и возвращает jqXHR. Её можно переопределить, чтобы использовать другую стратегию сохранения, например WebSockets, передачу XML или Local Storage.

Сигнатура метода Backbone.sync: sync(method, model, [options])

  • method — метод CRUD ("create", "read", "update" или "delete")
  • model — сохраняемая модель (или читаемая коллекция)
  • options — обратные вызовы success и error, а также все остальные параметры запроса jQuery

При реализации по умолчанию, когда Backbone.sync отправляет запрос на сохранение модели, её атрибуты сериализуются в JSON и отправляются в теле HTTP-запроса с типом содержимого application/json. В ответе JSON передавайте атрибуты модели, изменённые сервером и подлежащие обновлению на клиенте. В ответ на запрос "read" от коллекции (Collection#fetch) передавайте массив объектов с атрибутами моделей.

Когда модель или коллекция начинает sync с сервером, возникает событие "request". При успешном завершении запроса будет вызвано событие "sync", а при неудаче — событие "error".

Функцию sync можно переопределить глобально через Backbone.sync или на более локальном уровне, добавив функцию sync в коллекцию Backbone либо отдельную модель.

Обработчик sync по умолчанию сопоставляет CRUD с REST следующим образом:

  • create → POST /collection
  • read → GET /collection[/id]
  • update → PUT /collection/id
  • patch → PATCH /collection/id
  • delete → DELETE /collection/id

Например, обработчик Rails 4, отвечающий на вызов "update" от Backbone, может выглядеть так:

def update
  account = Account.find params[:id]
  permitted = params.require(:account).permit(:name, :otherparam)
  account.update_attributes permitted
  render :json => account
end

Ещё один совет по интеграции с версиями Rails до 3.1: отключите стандартное добавление пространства имён для вызовов to_json моделей, задав ActiveRecord::Base.include_root_in_json = false

ajaxBackbone.ajax = function(request) { ... };
Если вы хотите использовать пользовательскую AJAX-функцию или ваша конечная точка не поддерживает API jQuery.ajax и требуется изменить параметры, задайте Backbone.ajax.

emulateHTTPBackbone.emulateHTTP = true
Если нужно работать с устаревшим веб-сервером, не поддерживающим стандартный подход Backbone REST/HTTP, можно включить Backbone.emulateHTTP. При включении этого параметра запросы PUT, PATCH и DELETE будут подменяться HTTP-запросом POST с заголовком X-HTTP-Method-Override, содержащим исходный метод. Если также включён emulateJSON, исходный метод будет передан как дополнительный параметр _method.

Backbone.emulateHTTP = true;

model.save();  // POST to "/collection/id", with "_method=PUT" + header.

emulateJSONBackbone.emulateJSON = true
Если вы работаете с устаревшим веб-сервером, не поддерживающим запросы в формате application/json, включение Backbone.emulateJSON = true; приведёт к сериализации JSON в параметр model и отправке запроса с MIME-типом application/x-www-form-urlencoded, как при отправке HTML-формы.

Backbone.View

Представления Backbone — это скорее соглашение, чем код: они ничего не определяют за вас в отношении HTML или CSS и могут использоваться с любой библиотекой шаблонизации JavaScript. Общая идея состоит в том, чтобы организовать интерфейс в логические представления, связанные с моделями, каждое из которых можно обновлять независимо при изменении модели, не перерисовывая страницу. Вместо того чтобы разбирать объект JSON, искать элемент в DOM и вручную обновлять HTML, вы можете привязать функцию render своего представления к событию "change" модели — и теперь данные этой модели всегда сразу обновляются во всех местах интерфейса, где они отображаются.

extendBackbone.View.extend(properties, [classProperties])
Начните работу с представлениями, создав собственный класс представления. Вам потребуется переопределить функцию render, указать декларативные события и, возможно, задать tagName, className или id корневого элемента представления.

var DocumentRow = Backbone.View.extend({

  tagName: "li",

  className: "document-row",

  events: {
    "click .icon":          "open",
    "click .button.edit":   "openEditDialog",
    "click .button.delete": "destroy"
  },

  initialize: function() {
    this.listenTo(this.model, "change", this.render);
  },

  render: function() {
    ...
  }

});

Такие свойства, как tagName, id, className, el и events, также можно определить как функцию, если вы хотите отложить их определение до выполнения программы.

preinitializenew View([options])
Используется с представлениями в виде классов ES. Если вы определите метод preinitialize, он будет вызван при первом создании представления, до выполнения какой-либо логики создания экземпляра.

class Document extends Backbone.View {
  preinitialize({autoRender}) {
    this.autoRender = autoRender;
  }

  initialize() {
    if (this.autoRender) {
      this.listenTo(this.model, "change", this.render);
    }
  }
}

constructor / initializenew View([options])
Существует несколько специальных параметров, которые, если их передать, будут напрямую присвоены представлению: model, collection, el, id, className, tagName, attributes и events. Если в представлении определена функция initialize, она будет вызвана при первом создании представления. Чтобы создать представление, ссылающееся на элемент, уже имеющийся в DOM, передайте этот элемент в качестве параметра: new View({el: existingElement})

var doc = documents.first();

new DocumentRow({
  model: doc,
  id: "document-row-" + doc.id
});

elview.el
У всех представлений всегда есть элемент DOM (свойство el), независимо от того, был ли он уже вставлен на страницу. Благодаря этому представления можно отрисовывать в любое время и затем целиком вставлять в DOM, обеспечивая высокую производительность отрисовки интерфейса с минимальным числом перекомпоновок и перерисовок.

this.el может быть получен из строки селектора DOM или элемента; в противном случае он будет создан на основе свойств tagName, className, id и attributes представления. Если ни одно из них не задано, this.el будет пустым div, чего часто вполне достаточно. Ссылку на el также можно передать конструктору представления.

var ItemView = Backbone.View.extend({
  tagName: 'li'
});

var BodyView = Backbone.View.extend({
  el: 'body'
});

var item = new ItemView();
var body = new BodyView();

alert(item.el + ' ' + body.el);

$elview.$el
Кэшированный объект jQuery для элемента представления. Удобная ссылка, избавляющая от необходимости каждый раз заново оборачивать элемент DOM.

view.$el.show();

listView.$el.append(itemView.el);

setElementview.setElement(element)
Чтобы применить представление Backbone к другому элементу DOM, используйте setElement. Этот метод также создаст кэшированную ссылку $el и перенесёт делегированные события представления со старого элемента на новый.

attributesview.attributes
Набор атрибутов, которые будут заданы как атрибуты элемента HTML DOM в el представления (id, class, data-свойства и т. д.), или функция, возвращающая такой набор.

$ (jQuery)view.$(selector)
Если на странице подключён jQuery, у каждого представления есть функция $, которая выполняет запросы в пределах элемента представления. Если использовать эту функцию jQuery с ограниченной областью поиска, для поиска конкретных элементов в списке не потребуется включать в запрос идентификаторы моделей, и можно будет гораздо активнее полагаться на атрибуты классов HTML. Это эквивалентно выполнению: view.$el.find(selector)

ui.Chapter = Backbone.View.extend({
  serialize : function() {
    return {
      title: this.$(".title").text(),
      start: this.$(".start-page").text(),
      end:   this.$(".end-page").text()
    };
  }
});

templateview.template([data])
Хотя Backbone напрямую не предоставляет функцию шаблонизации для представления, часто удобно определить в представлениях функцию template. Так при отрисовке представления вы получаете удобный доступ к данным экземпляра. Например, с использованием шаблонов Underscore:

var LibraryView = Backbone.View.extend({
  template: _.template(...)
});

renderview.render()
Реализация render по умолчанию ничего не делает. Переопределите эту функцию своим кодом, который отрисовывает шаблон представления на основе данных модели и обновляет this.el новым HTML. Хорошим соглашением считается return this в конце render, чтобы обеспечить возможность цепочки вызовов.

var Bookmark = Backbone.View.extend({
  template: _.template(...),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

Backbone не ограничивает выбор предпочитаемого вами способа шаблонизации HTML. Функция render может даже собирать строку HTML или использовать document.createElement для создания дерева DOM. Однако мы рекомендуем выбрать удобную библиотеку шаблонизации JavaScript. Mustache.js, Haml-js и Eco — достойные альтернативы. Поскольку Underscore.js уже подключён на странице, доступен _.template — отличный выбор, если вы предпочитаете простой стиль шаблонов с интерполяцией JavaScript.

Какую бы стратегию шаблонизации вы ни выбрали, будет удобно, если вам никогда не придётся помещать строки HTML в JavaScript. В DocumentCloud мы используем Jammit, чтобы включать шаблоны JavaScript, хранящиеся в /app/views, в наш основной пакет ресурсов core.js.

removeview.remove()
Удаляет представление и его el из DOM, а также вызывает stopListening, чтобы удалить все связанные события, которые представление подключило с помощью listenTo.

eventsview.events or view.events()
Хеш events (или метод) можно использовать, чтобы указать набор событий DOM, которые будут связаны с методами вашего представления с помощью delegateEvents.

Backbone автоматически подключит обработчики событий при создании экземпляра, непосредственно перед вызовом initialize.

var ENTER_KEY = 13;
var InputView = Backbone.View.extend({

  tagName: 'input',

  events: {
    "keydown" : "keyAction",
  },

  render: function() { ... },

  keyAction: function(e) {
    if (e.which === ENTER_KEY) {
      this.collection.add({text: this.$el.val()});
    }
  }
});

delegateEventsdelegateEvents([events])
Использует функцию on из jQuery, чтобы декларативно задавать обработчики событий DOM в пределах представления. Если хеш events не передан напрямую, в качестве источника используется this.events. События записываются в формате {"event selector": "callback"}. Обработчиком может быть как имя метода представления, так и непосредственно тело функции. Если опустить selector, событие будет привязано к корневому элементу представления (this.el). По умолчанию delegateEvents вызывается за вас в конструкторе представления, поэтому при наличии простого хеша events все события DOM уже будут подключены, и вам не придётся вызывать эту функцию самостоятельно.

Свойство events также можно определить как функцию, возвращающую хеш events. Это упрощает программное определение событий и их наследование от родительских представлений.

Использование delegateEvents даёт ряд преимуществ по сравнению с привязкой событий к дочерним элементам вручную с помощью jQuery во время render. Все обработчики привязываются к представлению до передачи в jQuery, поэтому при вызове обработчиков this по-прежнему ссылается на объект представления. При повторном вызове delegateEvents, возможно, с другим хешем events, все обработчики удаляются и делегируются заново. Это удобно для представлений, которые должны вести себя по-разному в разных режимах.

Для одного события доступен вариант delegateEvents — delegate. На самом деле delegateEvents — это просто обёртка для нескольких событий вокруг delegate. Аналог undelegateEvents доступен как undelegate.

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

var DocumentView = Backbone.View.extend({

  events: {
    "dblclick"                : "open",
    "click .icon.doc"         : "select",
    "contextmenu .icon.doc"   : "showMenu",
    "click .show_notes"       : "toggleNotes",
    "click .title .lock"      : "editAccessLevel",
    "mouseover .title .date"  : "showTooltip"
  },

  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  },

  open: function() {
    window.open(this.model.get("viewer_url"));
  },

  select: function() {
    this.model.set({selected: true});
  },

  ...

});

undelegateEventsundelegateEvents()
Удаляет все делегированные события представления. Полезно, если нужно временно отключить представление или удалить его из DOM.

Утилиты

Backbone.noConflictvar backbone = Backbone.noConflict();
Возвращает объект Backbone к исходному значению. Возвращаемое значение Backbone.noConflict() можно использовать, чтобы сохранить локальную ссылку на Backbone. Это полезно при встраивании Backbone на сторонние сайты, где вы не хотите перезаписывать уже существующий Backbone.

var localBackbone = Backbone.noConflict();
var model = localBackbone.Model.extend(...);

Backbone.$Backbone.$ = $;
Если на странице есть несколько копий jQuery или вы просто хотите указать Backbone использовать определённый объект в качестве библиотеки для работы с DOM и Ajax, вам понадобится это свойство.

Backbone.$ = require('jquery');

debugInfodebugInfo();
Если вам всё же потребуется отправить отчёт об ошибке, эта функция поможет предоставить подробную информацию о вашей конфигурации. Она выводит объект JSON с информацией о версиях Backbone и его зависимостей через console.debug. Кроме того, она возвращает этот объект, чтобы при необходимости вы могли изучить его в коде.

debugInfo поставляется в отдельном модуле вместе с edge-версией и выпусками новее 1.5.0. Он доступен в формате UMD с тем же префиксом, что и backbone.js, но с debug-info.js в качестве имени файла. Также он доступен в экспериментальном формате ES-модулей по адресу backbone/modules/.

  <!-- browser embeds -->
  <script src="some-path-or-url/backbone.js"></script>
  <script src="some-path-or-url/debug-info.js"></script>
  <script>
    Backbone.debugInfo();
  </script>

  // CommonJS
  require('backbone/debug-info.js')();

  // ESM
  import debugInfo from 'backbone/modules/debug-info.js';
  debugInfo();

© 2010–2024 Jeremy Ashkenas, DocumentCloud
Licensed under the MIT License.
https://backbonejs.org/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API