1

Backbone を使い始めたばかりで、まだ内外を理解しています。

Underscore と Backbone を使用して JSON を単純に表示しようとしています。Underscore と $.getJSON を使用するだけで動作させることができますが、Backbone と接続しようとすると、試行内容に応じてさまざまなエラーが発生します。

また、モデルに値をハードコーディングすることで Backbone を動作させることもできましたが、すべてをまとめようとすると壁にぶつかります。どんな助けでも大歓迎です。

ここに私のアンダースコアテンプレートがあります:

<script type="text/html" id='trailTemplate'>

    <% _.each(trails,function(trail){ %>

        <%= trail.trailname %><br />

    <% }); %>

</script>

そして、ここに私のバックボーンコードがあります:

var Trail = Backbone.Model.extend({
    urlRoot: "trails.json"
});

var trail = new Trail({});

var TrailView = Backbone.View.extend({
    el: '.page',

    template: _.template($("#trailTemplate").html(), {trails:trail.fetch()}),

    render: function(){
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    }
});

var trailView = new TrailView({
    model: trail
});

trailView.render();

必要に応じて、ここに Trails.json があります

[
        {
            "trailhead": "Bear Lake",
            "trailname": "Bear Lake",
            "distance": ".5",
            "gain": "20",
            "level": "easy"
        },

        {
            "trailhead": "Bear Lake",
            "trailname": "Nymph Lake",
            "distance": ".5",
            "gain": "225",
            "level": "fairly easy"
        }
]
4

1 に答える 1

6

Your trails.json file contains an array with 2 objects, which both represent a single 'Trail'. So you should have a collection 'Trails' instead of a single model

var Trails = Backbone.Collection.extend({
  url: '/trails.json'
});

var trails = new Trails();

The underscore template function can be used in 2 ways:

  1. _.template(templateString) - compiles the templateString into function that can be evaluated when necessary
  2. _.template(templateString, data) - compiles and immediately evaluates the template with the given data

Now the way you are using is number 2 (the way you declare the template) combined with number 1 (how you use it inside render). Let's examine the template declaration:

template: _.template($("#trailTemplate").html(), {trails:trail.fetch()})

This is all good up until the point you try to give it the data -attribute. First of all you don't need to give the data at this point, you just want to create the template function that can be evaluated when the View renders. Second, the stuff you are trying to pass as data is not at all what you think it is.

trail.fetch() doesn't return the the fetch results, it returns the ajax handle for the ajax call that is made with fetch. Thankfully Backbone is made so you don't have to think about all this painful ajax stuff, but instead you can trust the events that Backbone emits. So whip out the Backbone Catalog o' Events and check out reset

"reset" (collection, options) — when the collection's entire contents have been replaced.

This is the event you collection will emit, after fetch (also sync, i think). Before this event is emitted, your collection will be empty, so there is no point in doing anything with it before hearing this reset event. So let's bring it all together now:

var TrailView = Backbone.View.extend({
  el: '.page',

  template: _.template($("#trailTemplate").html()), // no data attribute here

  initialize: function() {
    this.collection.on('reset', this.render);  // render after collection is reset
    this.collection.fetch();  // fetch the collection from the trails.json file
  }

  render: function(){
    // evaluate the template here
    this.$el.html(this.template(this.collection.toJSON())); 
    return this;
  }
});

var trailView = new TrailView({
  collection: trails
});

// trailView.render(); <- No need for this, because it will render itself

Hope this helps!

于 2013-01-29T11:13:09.817 に答える