2

我需要所有新的 MenuItem 模型都具有来自父集合的菜单属性。这是一个不起作用的基本示例(因为 this.collection 在 MenuItem 的默认函数中未定义)

var MenuItem, Menu, menu;

MenuItem = Backbone.Model.extend({
  defaults: function() {
    return {
      menu: this.collection.name
    }
  },

  // Fake Backbone sync
  sync: function(method, model, options) {
    if(typeof model.cid != 'undefined') {
      var cid = model.cid;
      model.unset('cid').set({id:cid}, {silent:true});
    }
    options.success(model);
  }

});

Menu = Backbone.Collection.extend({
  model: MenuItem,
  initialize: function(options) {
    this.name = options.name;
  }
});

menu = new Menu({name: "footer"});

menu.create({title: "Page", url: "/page"}, {
  success: function(model){
    console.log(model.get("menu")) // expect to be "footer"
  }
})
4

2 回答 2

1

我已经设法通过覆盖集合的创建方法来修复它,我仍然不确定这是否是正确的方法。

create: function(attributes, options) {
  return Backbone.Collection.prototype.create.call(
    this,
    _.extend({menu: this.name}, attributes),
    options
  );
}
于 2012-11-05T13:26:56.070 回答
1

对于新模型所在的每一种可能性:

我发现挂钩未记录的集合功能效果很好_prepareModel

通用集合

该集合可以按原样使用来替换默认的 Backbone 集合。它增加了

  • onNewModel一个要覆盖的新函数,它接收新模型实例和选项
  • new-model发送相同数据的自定义事件。
var Collection = Backbone.Collection.extend({
    /**
     * Hook into the native _prepareModel to offer a standard hook
     * when new models are added to the collection.
     */
    _prepareModel: function(model, options) {
        model = Collection.__super__._prepareModel.apply(this, arguments);
        if (model) {
            // call our new custom callback
            this.onNewModel(model, options);
            // trigger a new custom event
            this.trigger('new-model', model, options);
        }
        return model;
    },

    // Called when adding a new model to the collection.
    onNewModel: _.noop,
});

您自己的收藏可能是:

var Menu = Collection.extend({
    model: MenuItem,
    initialize: function(models, options) {
        this.name = options.name;
    }
    onNewModel: function(model, options) {
        model.set({ menu: model.get('menu') || this.name });
    },
});

保证里面model是一个BackboneModel实例onNewModel

概念证明

// The generic collection, put that in a file and include it once in your project.
var Collection = Backbone.Collection.extend({
  /**
   * Hook into the native _prepareModel to offer a standard hook
   * when new models are added to the collection.
   */
  _prepareModel: function(model, options) {
    model = Collection.__super__._prepareModel.apply(this, arguments);
    if (model) {
      this.onNewModel(model, options);
      this.trigger('new-model', model, options);
    }
    return model;
  },

  // Called when adding a new model to the collection.
  onNewModel: _.noop,
});

// Extend from the generic collection to make your own.
var Menu = Collection.extend({
  initialize: function(models, options) {
    this.name = options.name;
  },
  onNewModel: function(model, options) {
    model.set({
      menu: model.get('menu') || this.name
    });
    
    console.log("onNewModel menu:", model.get('menu'));
  },
});

// then use it
var menu = new Menu([
  // works with bare objects
  {
    title: "Page",
    url: "/page"
  },
  // or Model instances
  new Backbone.Model({
    title: "Other Page"
  })
], {
  name: "footer" // the collection option
});

// Listen to the custom event if you want
Backbone.listenTo(menu, 'new-model', function(model, options) {
    console.log("'new-model' triggered with", model.get('title'));
});

// or other collection methods
menu.add({
  title: "Page",
  menu: "won't be overriden"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

于 2016-11-07T22:47:47.930 回答