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

BackboneJS : the model is fetched, but toJSON() and get() methods don't work

仍在学习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()); returns 一个空对象。

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

由于 JavaScript 异步执行,您的 console.log(categories.toJSON());categories.fetch(); 完成执行之前 执行。

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

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

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

这是一个例子(见 fiddle),它做同样的事情(但是从 GitHub API 中提取数据作为例子,因为它们有一个 public API).

第二种方式有点复杂,但在 Backbone 应用程序中是一种更常见的模式。这种方式包括在 CategoriesView 中添加一个 initialize 函数,并为 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)。我一直认为这很奇怪,所以我想我应该把它放在这里:)