显示嵌套json集合的主干

Backbone displaying nested json collections

本文关键字:集合 嵌套 json 显示      更新时间:2023-09-26

不确定我到底哪里出了问题。我似乎无法获得模板来呈现嵌套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"
         }
      ]
   }
]

问题是等待来自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有一系列下划线方法。

      // 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文件。

因此,当我们把所有这些放在一起时,我们最终会得到:

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;
  }
});