"Как" сохранить всю коллекцию в Backbone.js-позвоночник.синхронизация или jQuery."Аякс"?
Я хорошо знаю, что это можно сделать, и я посмотрел на довольно много мест (в том числе:Лучшая практика для сохранения всей коллекции?). Но мне все еще не ясно, "как именно" это написано в коде? (сообщение объясняет это на английском языке. Было бы здорово иметь конкретное объяснение javascript :)
говорят, у меня есть коллекция моделей - сами модели могут иметь вложенные коллекции. Я переопределил метод toJSON() родительской коллекции, и я получаю действительный объект JSON. Я хочу "сохранить" всю коллекцию (соответствующий JSON), но backbone, похоже, не встроен в эту функциональность.
var MyCollection = Backbone.Collection.extend({
model:MyModel,
//something to save?
save: function() {
//what to write here?
}
});
Я знаю, что где-то вы должны сказать:
Backbone.sync = function(method, model, options){
/*
* What goes in here?? If at all anything needs to be done?
* Where to declare this in the program? And how is it called?
*/
}
после того, как "просмотр" будет выполнен с обработкой, он отвечает за то, чтобы сообщить коллекции "сохранить" себя на сервере (способный обрабатывать запрос на массовое обновление/создание).
вопросы:
- как / в чем писать код, чтобы "соединить все это вместе"?
- каково "правильное" расположение обратных вызовов и как указать обратный вызов "успех/ошибка"? Я имею в виду синтаксически?Я не совсем понимаю синтаксис регистрации обратных вызовов в магистрали...
если это действительно сложная работа, то мы можем вызвать jQuery.ajax в представлении и передать this.successMethod или this.errorMethod как успех/ошибка обратного вызова?? Будет ли она работать?
мне нужно синхронизировать с образом мышления позвоночника - я знаю, что я определенно чего-то не хватает w.r.t., синхронизация целых коллекций.
11 ответов:
моя непосредственная мысль заключается не в том, чтобы переопределить метод при сохранении метода на позвоночнике.Коллекция, но оберните коллекцию в другой костяк.Модель и переопределить метод toJSON на этом. Потом Позвоночник.js будет рассматривать модель как единый ресурс, и вам не нужно взломать путь назад, который слишком много думает.
обратите внимание, что костяк.Коллекция имеет метод toJSON, поэтому большая часть вашей работы выполняется за вас. Вам просто нужно прокси-метод toJSON вашей оболочки позвоночника.Модель Позвоночник.коллекция.
var MyCollectionWrapper = Backbone.Model.extend({ url: "/bulkupload", //something to save? toJSON: function() { return this.model.toJSON(); // where model is the collection class YOU defined above } });
очень простой...
Backbone.Collection.prototype.save = function (options) { Backbone.sync("create", this, options); };...даст вашим коллекциям метод сохранения. Имейте в виду, что это всегда будет размещать все модели коллекции на сервере независимо от того, что изменилось. параметры - это просто обычные параметры jQuery ajax.
Я закончил тем, что просто "сохранить" как метод и вызвал $.Аякс внутри него. Это дало мне больше контроля над ним без необходимости добавлять класс обертки, как предложил @brandgonesurfing (хотя мне очень нравится идея:), как уже упоминалось, поскольку у меня уже была коллекция.метод toJSON () переопределил все, что я приземлился, используя его в вызове ajax...
надеюсь, что это поможет кому-то, кто натыкается на него...
это действительно зависит от того, что контракт между клиентом и сервером. Вот упрощенный пример CoffeeScript, где PUT to
/parent/:parent_id/childrenС{"children":[{child1},{child2}]}заменит детей родителя на то, что находится в PUT и return{"children":[{child1},{child2}]}:class ChildElementCollection extends Backbone.Collection model: Backbone.Model initialize: -> @bind 'add', (model) -> model.set('parent_id', @parent.id) url: -> "#{@parent.url()}/children" # let's say that @parent.url() == '/parent/1' save: -> response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON())) response.done (models) => @reset models.children return responseэто довольно простой пример, вы можете сделать гораздо больше... это действительно зависит от того, в каком состоянии находятся ваши данные при выполнении save (), в каком состоянии они должны быть отправлены на сервер и что дает сервер спина.
если ваш сервер в порядке с PUT of
[{child1},{child2], тогда ваш позвоночник.линия синхронизации может измениться наresponse = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json').
ответ зависит от того, что вы хотите сделать с коллекцией на стороне сервера.
Если вам нужно отправить дополнительные данные С сообщением вам может понадобиться модель оболочки или реляционная модель.
С модель фантик вы всегда должны написать свой собственный парсить способ:
var Occupants = Backbone.Collection.extend({ model: Person }); var House = Backbone.Model.extend({ url: function (){ return "/house/"+this.id; }, parse: function(response){ response.occupants = new Occupants(response.occupants) return response; } });реляционной модели лучше, я думаю, потому что вы можете настроить их проще и вы можете регулировать с includeInJSON опция, атрибуты которой нужно поместить в json, который вы отправляете в свою службу rest.
var House = Backbone.RelationalModel.extend({ url: function (){ return "/house/"+this.id; }, relations: [ { type: Backbone.HasMany, key: 'occupants', relatedModel: Person, includeInJSON: ["id"], reverseRelation: { key: 'livesIn' } } ] });если вы не отправляете дополнительные данные вы можете синхронизировать саму коллекцию. Вы должны добавить сохранить метод для вашей коллекции (или прототипа коллекции) в этом случае:
var Occupants = Backbone.Collection.extend({ url: "/concrete-house/occupants", model: Person, save: function (options) { this.sync("update", this, options); } });
Я также был удивлен, что базовые коллекции не имеют встроенного сохранения. Вот что я положил на мою коллекцию позвоночника, чтобы сделать это. Я определенно не хочу повторять каждую модель в коллекции и сохранять независимо. Кроме того, я использую магистраль на бэкэнде, используя узел, поэтому я переопределяю родной
Backbone.syncчтобы сохранить в плоский файл на моем маленьком проекте-но код должен быть почти таким же:save: function(){ Backbone.sync('save', this, { success: function(){ console.log('users saved!'); } }); }
старый поток я знаю, что я в конечном итоге сделал следующее:
Backbone.Collection.prototype.save = function (options) { // create a tmp collection, with the changed models, and the url var tmpCollection = new Backbone.Collection( this.changed() ); tmpCollection.url = this.url; // sync Backbone.sync("create", tmpCollection, options); }; Backbone.Collection.prototype.changed = function (options) { // return only the changed models. return this.models.filter( function(m){ return m.hasChanged() }); }; // and sync the diffs. self.userCollection.save();довольно напрягаться вперед :)
вот простой пример:
var Books = Backbone.Collection.extend({ model: Book, url: function() { return '/books/'; }, save: function(){ Backbone.sync('create', this, { success: function() { console.log('Saved!'); } }); } });при вызове метода save () в вашей коллекции он отправит запрос метода PUT на определенный URL-адрес.
Я бы попробовал что-то вроде:
var CollectionSync = function(method, model, [options]) { // do similar things to Backbone.sync } var MyCollection = Backbone.Collection.extend({ sync: CollectionSync, model: MyModel, getChanged: function() { // return a list of models that have changed by checking hasChanged() }, save: function(attributes, options) { // do similar things as Model.save } });
принятый ответ довольно хорош, но я могу пойти еще на один шаг и дать вам код, который обеспечит запуск правильных событий для ваших слушателей, а также позволит вам передавать обратные вызовы событий ajax:
save: function( options ) { var self = this; var success = options.success; var error = options.error; var complete = options.complete; options.success = function( response, status, xhr ) { self.trigger('sync', self, response, options); if (success) return success.apply(this, arguments); }; options.error = function( response, status, xhr ) { self.trigger('error', self, response, options); if (error) return error.apply(this, arguments); }; options.complete = function( response, status, xhr ) { if (complete) return complete.apply(this, arguments); } Backbone.sync('create', this, options); }
для тех, кто все еще использует позвоночник.js в 2017 году принятый ответ не работает.
Попробуйте удалить переопределение toJSON () в модели оболочки и вызвать toJSON в коллекции при создании экземпляра оболочки модели.
new ModelWrapper(Collection.toJSON());
Comments