2013-12-17 113 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