BackboneJS:获取模型,但toJSON()和get()方法不起作用

时间:2015-06-11 01:01:12

标签: javascript backbone.js

还在学习Backbone,这是我的代码

const API_URL = 'http://api.brewerydb.com/v2';
const API_KEY = '********************************';

var Categories = Backbone.Model.extend({
    url: API_URL + '/categories/?key=' + API_KEY
});

var CategoriesView = Backbone.View.extend({
    tagName: 'ul',
    id: 'categories',
    render: function()
    {
        var html = '';

        for (var i = 0; i < this.model.get('data').length; i++)
        {
            html += '<li>' + this.model.get('data')[i].name + '</li>';
        }

        this.$el.html(html);
    }
});

var categories = new Categories();
categories.fetch();

console.log(categories.toJSON());

我的console.log(categories.toJSON());会返回一个空对象。

但是当我执行console.log(categories);时,attributes属性包含数据。如果我尝试使用任何这些属性,它也不起作用(undefined)。

1 个答案:

答案 0 :(得分:1)

由于JavaScript以异步方式执行,因此console.log(categories.toJSON());categories.fetch();执行完毕之前执行

这可以通过很多不同的方式解决,但这里有两个常见的方法:

第一种方法是使用Backbone.Model的fetch()方法,它接受successerror个回调:

categories.fetch({
  success: function() {
    console.log(categories.toJSON());        
  }
});

以下是一个示例(请参阅fiddle),它执行相同的操作(但是从GitHub API中提取数据作为示例,因为它们具有公共API)。

第二种方式有点复杂,但在Backbone应用程序中是一种更常见的模式。这种方式包括在initialize中添加CategoriesView函数,并为Backbone的同步事件添加事件监听器。该事件将触发回调,之后您可以执行渲染功能。

它还要求您在调用新视图构造函数时传入对模型的引用(请参阅下面代码中的最后一行以了解如何完成此操作。)

这可能看起来有点令人困惑,所以我又制作了另一个fiddle,显示了这一点,再次从GitHub API中提取数据。

除了GitHub API示例之外,您的代码现在看起来像这样:

const API_URL = 'http://api.brewerydb.com/v2';
const API_KEY = '********************************';

var Categories = Backbone.Model.extend({
    url: API_URL + '/categories/?key=' + API_KEY
});

var CategoriesView = Backbone.View.extend({
    tagName: 'ul',
    id: 'categories',
    initialize: function()
    {
        this.model.fetch();
        this.listenTo(this.model, 'sync', this.render);
    },
    render: function()
    {
        // Your data will show up
        // in this case
        console.log(categories.toJSON());

        var html = '';

        for (var i = 0; i < this.model.get('data').length; i++)
        {
            html += '<li>' + this.model.get('data')[i].name + '</li>';
        }

        this.$el.html(html);
    }
});

var categories = new Categories();

// Create a new instance of the view,
// and pass in the model you just
// created
var categoriesView = new CategoriesView({ model: categories });

您可能会注意到一个奇怪的事情是,在您看来,listenTo sync事件, fetch事件。这是因为从Backbone 1.0开始,model.fetch()实际上会触发sync事件(source)。我一直认为这很奇怪,所以我想我会把它丢在这里:)