Backbone TypeError view is not a constructor

2019-08-29 02:00发布

问题:

I'm trying an example from 'Developing Backbone.js applications' book. I've reproduced part of the code below. When app.js is invoked, I get the following error in renderBook method of LibraryView (library.js).

TypeError: app.BookView is not a constructor

Can someone help me please?

// View for book (site/js/views/book.js)

var app = app || {};

app.BookView = Backbone.View.extend({
    tagName: 'div',
    className: 'bookContainer',
    template: _.template( $('#bookTemplate').html() ),

    render: function() {
        // tmpl is a function that takes a JSON object and returns html

        // this.el is what we defined in tagName. use $el to get access 
        // to jQuery html() function
        this.$el.html( this.template( this.model.toJSON() ));

        return this;
    }
});

//View for library (site/js/views/library.js )

var app = app || {};

app.LibraryView = Backbone.View.extend({
    el: '#books',

    initialize: function( initialBooks ) {
        this.collection = new app.Library( initialBooks );
        this.render();
    },

    // render library by rendering each book in its collection
    render: function() {
        this.collection.each(function( item ) {
            this.renderBook( item );
        }, this );
    },

    // render a book by creating a BookView and appending the
    // element it renders to the library's element
    renderBook: function( item ) {
        var bookView = new app.BookView({
            model: item
        });
        this.$el.append( bookView.render().el );
    }
});

// The main app (site/js/app.js)

var app = app || {};

$(function() {
    var books = [
        { title: 'JavaScript: The Good Parts', author: 'Douglas Crockford', 
          releaseDate: '2008', keywords: 'JavaScript Programming' },
        { title: 'The Little Book on CoffeeScript', author: 'Alex MacCaw', 
          releaseDate: '2012', keywords: 'CoffeeScript Programming' },
        { title: 'Scala for the Impatient', author: 'Cay S. Horstmann', 
          releaseDate: '2012', keywords: 'Scala Programming' },
        { title: 'American Psycho', author: 'Bret Easton Ellis', 
          releaseDate: '1991', keywords: 'Novel Splatter' },
        { title: 'Eloquent JavaScript', author: 'Marijn Haverbeke', 
          releaseDate: '2011', keywords: 'JavaScript Programming' }
    ];

    new app.LibraryView( books );
});

The html file includes all the JS in the following order:

<script src="js/lib/jquery.min.js"></script>
<script src="js/lib/underscore-min.js"></script>
<script src="js/lib/backbone-min.js"></script>
<script src="js/models/book.js"></script>
<script src="js/collections/library.js"></script>
<script src="js/views/book.js"></script>
<script src="js/views/library.js"></script>
<script src="js/app.js"></script>

Thanks.

回答1:

Try wrapping your BookView & LibraryView declarations in onload $(function() {} blocks. Thats the only thing I can think of. Backbone.View.Extend is a function, and thus needs to be executed.

The way your currently doing it, you are setting app.BookView equal to the function Backbone.View.Extend, not the value returned by the function.