如何从JSON填充主干集合

时间:2015-10-09 18:34:25

标签: javascript json backbone.js-collections

拥有以下代码:

var Tasks = Backbone.Collection.extend({
    url: 'http://localhost:5000/tasks'
});

var TaskView = Backbone.View.extend({
    el: '.page',
    render: function() {
        var that = this;
        var tasks = new Tasks();

        tasks.fetch( {
            success: function(tasks) {
                var template = _.template($('#task-list-template').html(), {tasks: tasks.models});

                that.$el.html(template);
            }
        })
    }
});

var Router = Backbone.Router.extend({
    routes: {
        '' : 'home' // intentionally blank for the home page
    }
});

// Display logic
var taskListView = new TaskView({ });
var router = new Router();

router.on('route:home', function() {
    taskListView.render();
});

Backbone.history.start();

以下HTML:

<body>

    <div class="container">
        <h1>TODO app</h1>
        <hr />
        <div class="page"></div>
    </div>

    <script type="text/template" id="task-list-template">
        <table class="table striped">
            <thead>
            <tr>
                <th>Task</th>
                <th></th>
            </tr>
            </thead>
            <tbody>
            <% _.each(tasks.tasks, function(task) { %>
            <tr>
                <td><%=task.get('task') %></td>
                <td></td>
            </tr>
            <% }); %>
            </tbody>
        </table>
    </script>

    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
    <script type="text/javascript" src="todoapp.js"></script>

</body>

以及从AJAX请求返回的以下JSON:

{
  "tasks": [
    {
      "id": 6314025183,
      "task": "1"
    }
  ]
}

我想知道如何使用JSON数据填充Collection。我无法填写我的HTML表格。我怀疑我的收藏品没有被正确填写。

  1. 我如何验证集合的内容?
  2. 我是以正确的方式填写收藏品吗?
  3. 此代码基于来自Thomas Davis的视频,可在youtube上找到。 https://www.youtube.com/watch?v=FZSjvWtUxYk

1 个答案:

答案 0 :(得分:3)

你有两个问题。一个是代码相关的,一个是遗憾的API相关。

API问题可以通过两种方式解决,但我会先解决它。

Collection请求数据(来自url属性)时,它需要一个数据数组。不幸的是,您的API正在返回一个对象:

{
  "tasks": [
    {
      "id": 6314025183,
      "task": "1"
    }
  ]
}

这在很多API设计中非常常见,并且真正说明了对API有用的一般误解。

您会注意到实际想要的数据位于对象的tasks键中:

[
    {
      "id": 6314025183,
      "task": "1"
    }
]

它是一组任务对象,每个对象都有一个id和 - 我认为是 - 一个任务id

很好,所以你有两个选择:你可以修复API,以便对像/tasks这样的收集路由的请求返回集合:

[
    {
      "id": 6314025183,
      "task": "1"
    }
]

或者,您可以使用Backbone的parse方法来破解垃圾数据。

来自Collection.parse的文档:

  

如果您需要使用预先存在的API,或者更好地命名您的回复,请覆盖此内容。

这是一个简单的例子:

var Tasks = Backbone.Collection.extend({
    'url': 'http://localhost:5000/tasks',

    'parse': function( apiResponse ){
        return apiResponse.tasks;
    }
});

请注意该解析方法中包含的没有主页的信息。我怎么知道答复的关键是tasks

如果我是这位新代码的开发人员,那么我不会。我必须在API原始响应主体中搜索它的部落知识或知识。更好的解决方案是命名API响应以按要求返回集合。

您的第二个问题与您的代码有关。在您的代码中,您有一个Collection和一个View以及一个模板,但在您的模板中,您可以将您的任务视为一个简单的问题。 javascript对象,使用下划线循环键。

相反,请告诉您的收藏集如何表示数据。

集合是一组相关的Model s。

var Task = Backbone.Model.extend({});
var Tasks = Backbone.Collection.extend({
    'url': 'http://localhost:5000/tasks',
    'model': Task,

    'parse': function( apiResponse ){
        return apiResponse.tasks;
    }
});

现在,当您对集合进行保湿时,它将自动创建一个表示每组离散数据的模型。

您可以将视图更改为:

var TaskView = Backbone.View.extend({
    'el': '.page',
    'template': _.template($('#task-list-template').html()),
    'render': function() {
        var that = this;
        var tasks = new Tasks();

        tasks.fetch( {
            success: function() {
                that.$el.html( that.template( { 'tasks': tasks } ) );
             }
        })
    }
});

由于所有Backbone对象都以某种方式扩展下划线(see the docs for the details),因此您不需要在下划线中手动包装传入的集合。事实上,这样做几乎总会产生错误。您的模板可能如下所示:

<html>
<body>

    <div class="container">
        <h1>TODO app</h1>
        <hr />
        <div class="page"></div>
    </div>

    <script type="text/template" id="task-list-template">
        <table class="table striped">
            <thead>
            <tr>
                <th>Task</th>
                <th></th>
            </tr>
            </thead>
            <tbody>
            <% tasks.each( function( task ){ %>
            <tr>
                <td><%= task.get( 'task' ) %></td>
                <td></td>
            </tr>
            <% }); %>
            </tbody>
        </table>
    </script>

    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
    <script type="text/javascript" src="todoapp.js"></script>

</body>
</html>

此处发布的解决方案未经测试,但即使不能完全解决问题,也应该允许您进行主要的调试跳跃