如何使用 backbone.js 划分 JSON 集合结果

How to divide JSON collection result using backbone.js

目前我的json结果是这样的。

<div id="item-list">
   <div class="row" id="featured-item">
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
   </div>
</div>

这样可以吗?

<div id="item-list">
   <div class="row">
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
   </div>
   <div class="row">
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
   </div>
   <div class="row">
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
   </div>
   <div class="row">
      <div class="col-md-6"><p>Content Righ Here</p></div>
      <div class="col-md-6"><p>Content Righ Here</p></div>
   </div>
   <div class="row">
      <div class="col-md-6"><p>Content Righ Here</p></div>
   </div>
</div>

这是我当前的 jS 代码:

var Feed = Backbone.Model.extend({
    url: function () {
        //API LINK HERE
    },  
    defaults: {
        // SOME ATTRIBUTES HERE
    }
});

var Stream = Backbone.Collection.extend({    
    url: function () {
        //API LINK HERE
        return link;
    },
    page: 0,
    sort: 'date_created',
    order: 'desc',
    limit: 12,
    model: Feed,
    parse: function (response) {        
        $('.total_records').text(response._count);       
        var tags = response.data;
        this.totalRecords = response._count;
        return tags;
    }
}); 

// Master view
var DirectoryView = Backbone.View.extend({
    el: $("#main-section"),
    initialize: function () {   
        this.collection = this.options.collection;
        this.isLoading = false;
        this.render();
        this.collection.on("add", this.renderFeed, this);        
    },
    events: {
        'click #loadmore-feed' : 'loadMore'
    },
    render: function () {
        var that = this;
        this.isLoading = true;
        this.collection.fetch({success: function () {
                _.each(that.collection.models, function (item) {
                    that.renderFeed(item);
                }, this);
                that.isLoading = false;
                $("abbr.timeago").timeago();

                that.$el.find('#load-more-container').html(
                    _.template($('#load-more-template').html())
                );              
            }
        });

        if(!this.collection.totalRecords) {
            $('#load-more-container').hide();
        }
    },  
    loadMore: function () {
        $('#load-more-container').hide();
        if(this.collection.totalRecords > this.collection.page) {
            this.collection.page += 12;
            this.render();  
            $('#load-more-container').show();
        }      
    },
    renderFeed: function (item) {        
        var optionsView = new OptionsView({
            model: item
        });

        this.$el.find('#item-list > div').append($(optionsView.render().el).hide().fadeIn('slow'));

    }  
});

var OptionsView = Backbone.View.extend({
    tagName: "div",
    className: "col-md-6",
    template: $("#emp-list-item").html(),
    render: function () {
        var tmpl = _.template(this.template);        
        this.$el.html(tmpl(this.model.toJSON()));
        return this;
    }
}); 

HTML代码

<div id="main-section">
    <div id="item-list">
        <div class="row" id="featured-item"></div>
    </div>
    <div id="load-more-container"></div>
</div>
<!-- backbonejs view template -->
<script id="emp-list-item" type="text/template">      
    <p>Content Righ Here</p>
</script>
<script id="load-more-template" type="text/template">
    <p>
        <div class="progress xs progress-striped">
            <div class="progress-bar progress-bar-primary" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
                <span class="sr-only">60% Complete (warning)</span>
            </div>
        </div>
        <div class="tcenter">
            <a href="javascript:void(0)" id="loadmore-feed">Load more</a>
        </div>  
    </p>
</script>

<!-- Script for autoloading on mobile device -->
<script type="text/javascript">
    $(document).ready(function() {
        var paginatedItems = new Stream();
        var directoryView = new DirectoryView({collection: paginatedItems});
        $(window).scroll(function() {
            if (directoryView.$el.is(':visible') && !directoryView.isLoading && $(window).scrollTop() + $(window).height() > getDocHeight() - 400 ) {
                directoryView.loadMore();         
            }
        });
    });
</script>

您的问题标题涉及 JSON,但您的示例涉及 HTML,这是完全不同的问题。我不知道你是说 "can I produce this type of HTML structure" 还是 "can I make my collection hold this structure of data."

在不解决核心问题的情况下,您仍应将 fetch 移出 render,并使 render 发生在 success 上。例如:

initialize: function(models) {
    // ...do stuff...
    if (!models)
         this.fetch({success: this.render, error: this.error});
    _.bindAll(this, 'render', 'error', 'render');
},

在你的 success 中,你应该为 render:

做准备
render: function(collection) {
    var modelsFlat = collection.models;
    var nested = _(list).chain().partition(function(x) {

        // below makes an array of evens and odds indices

        return (_(list).indexOf(x) % 2) == 0;  

    }).zip()           // this turns columns into rows, ie [[1,3,5],[2,4,6]] => [[1,2],[3,4],[5,6]]
      .value();        // this unwraps (no more chaining)

    _(nested).each(function(n) {
        var inner = new Backbone.Collection(n);
        var innerView = new OptionsView(inner);
        innerView.render();
    });
    // Do the rest of your current render
}

而您的新 DirectoryItemView 几乎就是 OptionsView,其中不涉及任何 server-side 内容。

所以这个:

  1. 在外部视图的 initialize 上调用 fetch 以获得外部视图 collection
  2. success 调用 render
  3. render,将每对项目重新组织成一个新的小 collection
  4. 在每个 collection 上,用那个 collection 创建一个新的内部 OptionsView 并渲染它
  5. 通过渲染外部视图的其余部分完成。