Backbone嵌套视图 - 在模板中错误设置子视图属性

时间:2012-12-23 11:23:57

标签: backbone.js handlebars.js mv

我正在尝试创建一个Backbone模型(让我们称之为Library),其中包含其他模型的集合(让我们称之为Books)。我提供了一个视图 - LibraryView,它创建了一个书籍案例的HTML,其中包含由BookView生成的HTML表示的一组书籍。另外,我使用Handlebars.js作为我的模板系统。

我遇到的问题是,在我通过BookView函数传递之前,我的render()会在this.el元素上返回奇怪的html。

LibraryModel模型

  var LibraryModel = Backbone.Model.extend({

    initialize: function() {

      var books = new BookCollection();

      _.each(book_data.books, function(value, index) {
        books.add(new Book());
      });

      this.books = books;

    }
  });

LibraryView视图:

 var LibraryView = Backbone.View.extend({

    el: "#library",

    render: function() {

      var t = this;

      this.model.books.each(function(book, index) {
        //create new view for each Book model in the books collection
        var view = new BookView(book);
        //append HTML produced by the BookView into LibraryView el element
        t.$el.append(view.render().$el);
      });

      return this;  
    },

    initialize: function() {
      //snip
    }
  });

BookView查看:

  var BookView = Backbone.View.extend({

    render: function() {
      var viewmodel = this.model;
      var source = $("#book-template").html();
      var template = Handlebars.compile(source);
      var html = template(viewmodel.toJSON());

      console.log(html); //prints <div test="wtf" anotherTest="123"><b>wtf</b> 123</div>
      this.$el.html(html);

      return this;  
    },

    initialize: function(book) {
      console.log(this.el.outerHTML); //prints <div test="wtf" anotherTest="123"></div>
      this.model = book;
      this.listenTo(this.model, "change", this.render);
    }
  });

我提供的模板是:<b>{{test}}</b> {{anotherTest}}

BookModel模型

  var BookModel = Backbone.Model.extend({
    defaults: {
      test: "wtf",
      anotherTest: 123
    },

    initialize: function() {
        //snip
    }
  });

基本上,我遇到的问题是我的BookView会生成奇怪的HTML,其中每个模型属性都附加到Backbone生成的div,如下所示:

<div test="wtf" anotherTest="123">
<b>wtf</b> 123
</div>

我没有在代码中的任何其他位置设置任何属性 - 这两个值都只来自默认值。

另外,我确认这不是Handlebars正在做的事情,因为Model-attributes作为HTML-atributes插入到div模型的Backbone生成BookView中(注意,我没有提供tagName)或手动,我希望Backbone为我创建一个div。)

所以这就是我被困住的地方。我为BookView为列表中的每个模型生成了一个完美的HTML列表,但由于某种原因,Backbone生成的div包装器在其HTML属性中包含每个Model属性,如下所示:

<div id="#library">
<div test="wtf" anotherTest="123"><b>wtf</b> 123</div>
<div test="wtf" anotherTest="123"><b>wtf</b> 123</div>
<div test="wtf" anotherTest="123"><b>wtf</b> 123</div>
</div>

我真的把头发拉过来,我怀疑它与我试图使用View-in-a-View的事实有关。

你以前遇到过类似的问题吗?你有很好的Backbone应用程序示例,其中MasterView呈现ChildViews的集合吗?

1 个答案:

答案 0 :(得分:2)

创建新的BookViews时,你做的很奇怪。该视图期望初始化BookModel。但是,initialize()方法始终需要按惯例调用attributes的对象。您应修改BookView,使其符合以下条件:

var BookView = Backbone.View.extend({

    render: function() {
       // keep the same code
    },

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

并在LibraryView中使用:

var view = new BookView({ model : book });

而不是之前的:

var view = new BookView(film); // which is a typo, and should pass book and not film

所以现在你得到了预期的结果。

<div id="library">
    <div><b>wtf</b> 123</div>
    <div><b>wtf</b> 123</div>
    <div><b>wtf</b> 123</div>
</div>

请注意,initialize(attributes)会自动使用该映射调用set,因此您无需亲自调用set(attr, value)。考虑到这一点,我们可以理解为什么该视图具有两个属性,这两个属性实际上是您的两个模型的属性(在初始化时它们是set()。)