2013-12-17 82 views
0

不知道我到底在哪里出错。我似乎无法让模板在我的嵌套json中呈现标题属性。我在线上学习了一个教程,通过这种方式牵着我的手,但我碰到了一堵砖墙,无法弄清楚它为什么不能渲染。任何帮助将不胜感激。显示嵌套json集合的主干

这是我的模板和html。

<script id="albumTemplate" type="text/template"> 
    <p><%= title %></p> 
    </script> 
    <script id="subalbumTemplate" type="text/template"> 
    <p><%= title %></p> 
    </script> 

    <div class="row"> 
    <div class="six columns"><h5>Albums</h5></div> 
    <div class="six columns"><h5>Sub-Albums</h5></div> 
    </div> 
    <div class="row" style="color: #333;"> 
    <div class="six columns" id="categories"></div> 
    <div class="six columns" id="sub-cat"></div> 
    </div> 

这里是我的app.js

 app.Subalbum = Backbone.Model.extend({ 
      initialize: function() { 
       this.subId = this.get('id'); 
       this.subTitle = this.get('title'); 
       this.subImg = this.get('image'); 
       this.subCanvas = this.get('canvas'); 
       this.subSize = this.get('size'); 
      } 
     }); 
     app.Subalbums = Backbone.Collection.extend({ 
      model: app.Subalbum 
     }); 
     app.Album = Backbone.Model.extend({ 
      initialize: function() { 
       this.subs = new app.Subalbums(this.get('subalbum')); 
       this.subs.parent = this; 
       this.albumId = this.get('id'); 
       this.albumTitle = this.get('title'); 
       this.albumImg = this.get('image'); 
      } 
     }); 
     app.Albums = Backbone.Collection.extend({ 
      model: app.Album, 
      url: 'albums.json', 
      parse: function (data) { 
       return data; 
      } 
     }); 

     app.AlbumCollectionView = Backbone.View.extend({ 
      el: $("#categories"), 

      initialize: function() { 
       _.bindAll(this, 'render'); 
       this.model.on('reset', function() { 
        this.render(); 
       }, this); 
      }, 

      render: function (event) { 
       _.each(this.model.models, function (album) { 
        //console.log(album.subs); 
        $(this.el).append(new app.AlbumView({ 
         model: album 
        }).render().el); 
       }, this); 
       return this; 
      } 
     }); 

     app.AlbumView = Backbone.View.extend({ 
      template: _.template($("#albumTemplate").html()), 
      initialize: function() { 
       _.bindAll(this, 'render'); 
       // Subalbum View should be instantiated and called from inside the initialize function of the Parent View 
       this.subView = new app.SubalbumView({ 
        model: this.model.subs 
       }); 
       this.subView.parentView = this; // this assignment connects the child view to the parent view 
       $("#sub-cat").append(this.subView.render().el); // subView should "return this" from child render() function 
      }, 
      render: function() { 
       //console.log(this.model.subs); 
       //$(this.el).html("<p>" + this.model.get("title") + "</p>"); 
       $(this.el).append(this.template(this.model.toJSON())); 
       return this; 
      } 
     }); 

     app.SubalbumView = Backbone.View.extend({ 
      template: _.template($("#subalbumTemplate").html()), 
      initialize: function() { 
       _.bindAll(this, 'render'); 
       this.model.on('reset', function() { 
        this.render(); 
       }, this); 
      }, 

      render: function (event) { 
       _.each(this.model.models, function (subalbum) { 
        $(this.el).append("<p>" + subalbum.get("title") + "</p>"); 
        //$(this.el).html(this.template(subalbum.toJSON())); 
       }, this); 
       return this; 
      } 
     }); 

     app.AlbumRouter = Backbone.Router.extend({ 
      routes: { 
       "": "indexRoute" 
      }, 
      indexRoute: function() { 
       this.albumList = new app.Albums(); 
       this.albumList.fetch(); 
       this.albumAppView = new app.AlbumCollectionView({ 
        model: this.albumList 
       }); 
      } 
     }); 

     var albumRoute = new app.AlbumRouter(); 
     Backbone.history.start(); 

这里是albums.json文件结构。

[ 
    { 
     "pid":0, 
     "title":"Blues Singer", 
     "image":"blues_singer.jpg", 
     "subalbum":[ 
     { 
      "pid":0, 
      "title":"Another Realm", 
      "image":"another_realm.jpg" 
     }, 
     { 
      "pid":1, 
      "title":"Ascendant", 
      "image":"ascendant.jpg" 
     }, 
     { 
      "pid":2, 
      "title":"Ascent", 
      "image":"ascent.jpg" 
     } 
     ] 
    }, 
    { 
     "pid":1, 
     "title":"Destiny", 
     "image":"destiny.jpg", 
     "subalbum":[ 
     { 
      "pid":0, 
      "title":"Cathedral of Trees", 
      "image":"cathedral_of_trees.jpg" 
     }, 
     { 
      "pid":1, 
      "title":"Come Up Here", 
      "image":"come_up_here.jpg" 
     }, 
     { 
      "pid":2, 
      "title":"Crystal Forest", 
      "image":"crystal_forest.jpg" 
     } 
     ] 
    }, 
    { 
     "pid":2, 
     "title":"Eagle", 
     "image":"eagle.jpg", 
     "subalbum":[ 
     { 
      "pid":0, 
      "title":"Curved Road", 
      "image":"curved_road.jpg" 
     }, 
     { 
      "pid":1, 
      "title":"Dawn Breaking", 
      "image":"dawn_breaking.jpg" 
     }, 
     { 
      "pid":2, 
      "title":"Dawn", 
      "image":"dawn.jpg" 
     } 
     ] 
    }, 
    { 
     "pid":3, 
     "title":"Evening Harvest", 
     "image":"evening_harvest.jpg", 
     "subalbum":[ 
     { 
      "pid":0, 
      "title":"Destiny", 
      "image":"destiny.jpg" 
     }, 
     { 
      "pid":1, 
      "title":"Destiny2", 
      "image":"destiny2.jpg" 
     }, 
     { 
      "pid":2, 
      "title":"Eagle Rising", 
      "image":"eagle_rising.jpg" 
     } 
     ] 
    } 
] 

回答

1

问题是你等待this.albumList.fetch()reset事件,但是reset默认情况下不触发的,所以你需要做的传递{reset:true}fetch。这是一个JSFIDDLE

indexRoute: function() { 
    this.albumList = new app.Albums(); 

    // This view will render when the model's reset event is triggered. 
    // Since albumList is a collection, it should identified as such. 
    this.albumAppView = new app.AlbumCollectionView({ 

    // albumList is a collection and it should identified as such. 
    // instead of model:this.albumList - now within albumAppView, you will have 
    // access to the collection via this.collection instead of this.model 
    collection: this.albumList  
    }); 

    this.albumList.fetch({reset:true}); 
} 

一些副作用建议(我会挑上你的AlbumCollectionView),但同样适用于你的其他意见,以及:

  1. 相反的el: $("#categories")你可以只使用一个字符串el:'#categories'

  2. initialize中,当您利用listenTo时,您正在使用this.model.on。使用listenTo的主要优势是在调用remove上查看时,事件监听器将为您清理。

    // this works. 
    this.collection.on('reset', function() { 
        this.render(); 
        }, this); 
    
    // can be written as (remember the we changed model to collection above). 
    this.listenTo(this.collection,'reset',this.render); 
    
  3. 移动到你的render功能,Backbone.Collection具有连接到他们的underscore methods摆。

    // while this works 
        _.each(this.collection.models, function (album) { ... }); 
    
        // can be written as: 
        this.collection.each(function(album) { ... }); 
    }); 
    
  4. $(this.el),是有点过时,你可以使用this.$el,这仅仅是一种观点的元素缓存jQuery对象。 $el documentation

所以,当我们把它放在一起,我们风与:

app.AlbumCollectionView = Backbone.View.extend({ 
    el: '#categories', 

    initialize: function() { 
    this.listenTo(this.collection,'reset', this.render); 
    }, 

    render: function() { 
    this.collection.each(function (album) { 
     var albumView = new app.AlbumView({model: album}); 
     this.$el.append(albumView.render().el); 
     }, this); 
    return this; 
    } 
}); 
+0

太谢谢你了!这是我收到的最好,最具描述性的答案之一。这也是一个很好的奖励,收到我的代码和不同的方式去做事情的一些反馈:) – Anks

+0

不知道你是否可以帮助我多一件事,但我试图改变它的渲染顺序。我想看到发生的事情是[专辑标题]然后[专辑标题的儿童],然后[NextAlbum标题],然后[专辑标题的孩子]等。 – Anks

+0

您的意思是这样的http://jsfiddle.net/ 93mp9 /?如果是这样,这是因为你正在渲染你的观点。 – fbynite