模型视图仅显示默认值

Model view shows only default values

我的 backbone.js 代码有什么问题?
加载产品页面时,仅显示模型的默认值...
虽然在控制台中我看到正确的数据...

这是我的模型:

var app = app || {};
app.Product = Backbone.Model.extend({
    defaults: {
        coverImage: 'img/placeholder.png',
        id: null,
        name: 'Unknown',
        price: '100'
    }
});

Collection:

var app = app || {};
app.ProductList = Backbone.Collection.extend({
    model: app.Product,
    url: 'php/listProducts.php'
});

有我的看法:

var app = app || {};
app.ProductItemView = Backbone.View.extend({
    template: _.template($('#productPage').html()), 

    initialize: function(options) {
        var id = options.id;
        this.model = new app.Product();
        this.collection = new app.ProductList();
        this.collection.fetch({
            success: function(collection){
                console.log(collection.toJSON());
                console.log('Collection models: ', collection.models[id-1]);
                this.model = collection.models[id-1];
                console.log('This model: ', this.model);
            }
        });

        this.render();
    },

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


});

路由器:

var app = app || {};
app.Router = Backbone.Router.extend({
    routes: {
        "product/:id": "productPageShow"
    },

    initialize: function () {
        this.$content = $("#product-list");
    },

    productPageShow: function(id) {
        app.prodItView = new app.ProductItemView({ id: id });
        this.$content.html(app.prodItView.el);
    }

});

$(function() {
    new app.Router();
    Backbone.history.start();
});

我的模板:

<div class="container">    
    <div id="product-list"></div>
</div>

<script id="productPage" type="text/template">
    <div>
        <img src="<%= coverImage %>" class="img-responsive" style="width:100%" alt="<%= name %>">
    </div>
    <div>
        <h2><%= name %></h2>
    </div>
    <div>
        <h3><%= price %></h3>
    </div>
</script>

控制台图像:

console image

发生这种情况是因为 'fetch' 是一个异步操作,因此 render() 将始终在 fetch() 调用的 success() 回调之前被调用。

一些额外的资源,如果你想要的话:

https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started

http://backbonejs.org/#Model-fetch

在代码中直观地解释 initialize 方法中的执行顺序:

var app = app || {};
app.ProductItemView = Backbone.View.extend({
    template: _.template($('#productPage').html()), 

    initialize: function(options) {
        // 1
        var id = options.id;
        // 2
        this.model = new app.Product();
        // 3
        this.collection = new app.ProductList();
        // 4 - fetch is only called and ajax request is sent to your backend.
        //     success callback is still not called
        this.collection.fetch({
            success: function(collection) {
                // 6 - when you get the data from the server the callback is called
                //     but the page is already rendered at this time
                console.log(collection.toJSON());
                console.log('Collection models: ', collection.models[id-1]);
                this.model = collection.models[id-1];
                console.log('This model: ', this.model);
            }
        });

        // 5
        this.render();
    },

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

修复应该相当简单,只需调用成功回调底部的渲染方法并绑定到视图的正确上下文:

var app = app || {};
app.ProductItemView = Backbone.View.extend({
    template: _.template($('#productPage').html()), 

    initialize: function(options) {
        var id = options.id;
        this.model = new app.Product();
        this.collection = new app.ProductList();
        this.collection.fetch({
            success: _.bind(function(collection) {
                console.log(collection.toJSON());
                console.log('Collection models: ', collection.models[id-1]);
                this.model = collection.models[id-1];
                console.log('This model: ', this.model);

                // Moved render call here
                this.render();
            }, this)
        });

    },

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

此外,正如一般建议.. 永远不要直接从集合中选择模型.. 在集合上使用提供的 get 方法并传递您需要的模型 id .. 使用collection.get(mnodelId) 超过 collection.models[arrayIndexOfTheModel]