在Backbone.js中的视图中实例化模型是一种反模式吗?

时间:2014-02-05 19:14:56

标签: javascript backbone.js backbone-views decoupling backbone-model

在开发Backbone应用程序时,我经常发现自己在处理嵌套数据时在视图中实例化模型。以下是一些示例数据:

{
  name: Alfred,
  age 27,
  skills: [
    {
      name: 'Web development',
      level: 'Mediocre'
    },
    {
      name: 'Eating pizza',
      level: 'Expert'
  ]
}

假设我有一些视图PersonView,它将人物对象PersonModel作为其模型(其中Alfred将是一个实例)。让我们说我想把这个人的技能渲染为子视图。此时,我创建了一个新视图和一个用于处理嵌套技能数据的新模型。这就是我怀疑我做错了什么,或者至少是一些不理想的事情。

var SkillModel = Backbone.Model.extend();

var SkillView = Backbone.View.extend({
  tagName: 'li',
  initialize: function() {
    this.render();
  },
  render: function() {
    this.$el.html(someTemplate(this.model));
  }
});

var PersonView = Backbone.View.extend({
  el: ...
  initialize: ...
  renderSkills: function() {
    _.each(this.model.get('skills'), function(skill) {
      var skillModel = new SkillModel(skill);
      var skillView = new SkillView({ model: skillModel });

      self.$el.append(skillView.el);
    })
  }
});

我真的应该这样做,还是有一些更好的模式,这不涉及第三方库,解决了这个问题?我觉得我并没有以最好的方式将观点和模型脱钩。如果你想要一个具体的问题:这是反模式吗?

1 个答案:

答案 0 :(得分:1)

视图用于视图逻辑,数据逻辑模型。

考虑拥有这样的模型:

var SkillModel = Backbone.Model.extend({
});
var SkillsCollection = Backbone.Collection.extend({
    model : SkillModel
});
var PersonModel = Backbone.Model.extend({

    /*
    ** Your current model stuff
    */

    //new functionality 

    skills : null,

    initialize : function(){
        //set a property into the model that stores a collection for the skills
        this.skills = new SkillsCollection;
        //listen to the model attribute skills to change
        this.on('change:skills', this.setSkills);
    },

    setSkills : function(){
        //set the skills of the model into skills collection
        this.skills.reset( this.get('skills') );
    }

});

所以在你看来renderSkills会是这样的:

var PersonView = Backbone.View.extend({
  renderSkills: function() {
     //this.model.skills <- collection of skills
    _.each(this.model.skills, function(skill) {
      var skillView = new SkillView({ model: skillModel });

      self.$el.append(skillView.el);
    })
  }
});

我的伪代码试图适应你的示例代码。但是如果你明白了,基本上你可以在模型中有一个嵌套的模型或集合,所以在视图中没有需要的数据交互/设置,一切都在模型中。我也按你的要求回答,没有第三方处理事情。但是不要介意看看这种插件的来源: https://github.com/afeld/backbone-nested

更新:根据评论,我提供了模型示例的设置:

var m = new PersonModel();
//nested collection is empty
console.log(m.skills.length);
m.set({skills : [{skill1:true}, {skill1:true}]});
//nested collection now contains two children
console.log(m.skills.length);

正如您所看到的,模型用法“始终”只是一组属性,而模型是处理它的模型。您的视图应该使用技能作为视图如何使用任何其他集合。你可以做一个.each迭代,或者更值得听一下这个集合上的添加,重置等事件(但这是本问题范围之外的其他主题)。

实施例: http://jsfiddle.net/9nF7R/24/