Backbone.js Uncaught ReferenceError

2019-08-19 05:17发布

问题:

Im new to backbone, trying to fetch json from the Wordpress json plugin and render into a template, but when looping through posts I get the following error Uncaught ReferenceError: posts is not defined Any help appreciated. Thanks...

   jQuery(function($) {
    var Post = Backbone.Model.extend();
    var Posts = Backbone.Collection.extend({
        model: Post,
        url: '/api/get_post/?json=get_recent_posts',
        parse: function(resp) {
            console.log("posts", resp);
            return resp;
        }
    });
    var listView = Backbone.View.extend({
        el: '#content',
        template: _.template($("#post-template").html()),
        initialize: function() {
            this.model.bind("reset", this.render, this);
        },
        render: function() {
            $(this.el).html(this.template(this.model.toJSON()));
            return this;
        }
    });
    var AppRouter = Backbone.Router.extend({
        routes: {
            "!/archive": "archive"
        },
        archive: function() {
            this.postList = new Posts();
            this.postListView = new listView({
                model: this.postList
            });
            this.postList.fetch();
            this.postListView.render();
        }
    });
    var app = new AppRouter();
    Backbone.history.start();
});

Template

<script id="post-template" type="text/template">
    <ul>
      <% _.each(posts, function(post) { %>
        <li id="<%= post.id %>">
          <a href="<%= post.url %>"><%= post.thumbnail %></a>
        </li>
      <% }); %>
    </ul>
</script>

Json

{
    "status": "ok",
    "count": 1,
    "count_total": 1,
    "pages": 1,
    "posts": [{
        "id": 4,
        "type": "post",
        "slug": "test-post",
        "url": "http:\/\/localhost:8888\/2013\/04\/test-post\/",
        "status": "publish",
        "title": "Test Post",
        "title_plain": "Test Post",
        "content": "",
        "excerpt": "",
        "date": "2013-04-17 15:12:21",
        "modified": "2013-04-19 14:13:00",
        "categories": [],
        "tags": [],
        "author": {
            "id": 1,
            "slug": "admin",
            "name": "admin",
            "first_name": "",
            "last_name": "",
            "nickname": "admin",
            "url": "",
            "description": ""
        },
        "comments": [],
        "comment_count": 0,
        "comment_status": "closed",
        "thumbnail": "http:\/\/localhost:8888\/wp-content\/uploads\/2013\/04\/test-image-150x150.jpg"
    }]
}

回答1:

Calling Collection#toJSON will return an array. Therefore there is no posts key. Try using $(this.el).html(this.template(this.model.toJSON()[0])); as you only have one model in your collection (which is weird).

You may want to parse your response in the parse methods to return resp.posts so your collection has more meaning and actually creates one Post model per post.



回答2:

Try to do something like:

$(this.el).html({
   posts : this.template(this.model.toJSON())
});

instead of:

$(this.el).html(this.template(this.model.toJSON()));


回答3:

If you want to use posts as the variable that contains the collection/array in your underscore template, you need to pass it as a property to the template function:

$(this.el).html(this.template({ posts: this.model.toJSON() } ));

I would have also thought your Posts Collection class should have returned the posts in the parse function as shown below (as the posts are a property of the JSON that's being returned):

var Posts = Backbone.Collection.extend({
    model: Post,
    url: '/api/get_post/?json=get_recent_posts',
    parse: function(resp) {
        console.log("posts", resp);
        return resp.posts || [];  // grab the posts from the JSON 
    }
});

And, often by convention you might want to switch to using the collection attribute of the View:

this.postListView = new listView({
     collection: this.postList
});

And then change your template call: { posts: this.collection.toJSON() }.