如何在骨干网中获取具有特定ID的项目?

时间:2014-01-08 21:37:24

标签: javascript backbone.js

我正在尝试使用骨干从集合中获取特定项目。我正在documentation工作,并使用Backbone.js fetch with parameters,但仍然觉得我在猜测语法。

这是我最好的猜测:

 var accounts, myJob;
     accounts = new JobCollection();
     myJob = accounts.fetch({
           data: $.param({
           id: '7a107f87-be69-5efa-107c-c045e75940cf'
        })
     });
 return console.log(myJob); 

如何获取id为= 7a107f87-be69-5efa-107c-c045e75940cf的作业?

以下是定义集合的coffeescript:

class JobCollection extends Backbone.Collection
    localStorage: new Backbone.LocalStorage("cl-job")
    url:'/jobs'

4 个答案:

答案 0 :(得分:4)

为什么要在获取单个模型时使用集合?集合是模型列表,模型是具有ID的模型。

尽管如此,你可以很容易地做到这一点:

var job = new JobModel({id: '7a107f87-be69-5efa-107c-c045e75940cf'});
job.fetch({success: doSomethingWithFetchedModel, error: handleError});

如果您想通过集合执行此操作,您可以执行以下操作:

var jobs = new JobCollection():
jobs.fetch({success: function(collection, resp, opts){
    console.log(collection.get('7a107f87-be69-5efa-107c-c045e75940cf''));
});

这里的不同之处在于,当您获取一个集合时,它将获得该类型的所有模型,因此您需要在该集合中找到该模型,而使用单个模型,您只需返回该模型即可寻找。

答案 1 :(得分:1)

在Backbone中, fetch 用于通过Ajax调用从服务器检索数据。因此,您可以使用fetch从服务器返回作业列表。要在具有特定ID的作业集合中查找作业,您可以在集合中使用 where findWhere 函数。

以下是Collection fetch示例:

var JobModel = Backbone.Model.extend({});

var Jobs = Backbone.Collection.extend({
  model: JobModel,
  url: 'some/url/path/to/jobs.json',                        
  parse: function (response) {
    // parse jobs
  }
});

var jobs = new Jobs();
jobs.fetch(); // returns list of jobs

如果您的作业模型的属性为“id”,则可以使用以下作业从上述作业集合中选择特定作业:

var job = jobs.findWhere({ id: '7a107f87-be69-5efa-107c-c045e75940cf' });

答案 2 :(得分:0)

借用Jimmy和tkone。

如果要在不使用集合的情况下获取单个模型,Model Model需要定义urlRoot属性,以便同步调用知道在AJAX调用中使用的url。或者,您可以设置模型的集合,并在执行获取时依赖集合的url属性。

选项A(将urlRoot属性添加到模型中):

class JobModel extends Backbone.Model
urlRoot:'/jobs'

var myJob = new JobModel({id: '7a107f87-be69-5efa-107c-c045e75940cf'});
job.fetch({
    success: function () {
      console.log(myJob); 
    }
 });

选项B(使用JobCollection对象的url属性):

 var accounts, myJob;
 accounts = new JobCollection();
 myJob = new JobModel({id: '7a107f87-be69-5efa-107c-c045e75940cf'});
 myJob.collection = accounts;
 myJob.fetch({
    success: function () {
      console.log(myJob); 
    }
 });

答案 3 :(得分:0)

当我看到这个问题时,它提醒了我很多JérômeGravel-Niquets Todo列表应用程序,因为它使用本地存储并存储数据列表,这似乎是演示如何完成这项工作的好方法名单。我将待办事项清单改编为工作清单,并试图涵盖工作清单要求。

只是为了澄清一些要点:fetch用于加载集合,正如Jimmy所说,findWhere是如何在集合中找到一个项目(它们像一个简单的数据库一样工作)而你不会将url作为属性传递使用本地存储时。

这是我想出的,我试图尽可能简洁:

(无法让js依赖项在jsFiddle中工作)

jobs.js:

// modified Jérôme Gravel-Niquets Todo list Application to create a Job list
// as it demonstartes the same usage and principles
// http://backbonejs.org/examples/todos/index.html
$(function() {
    var Job = Backbone.Model.extend({
        // Default attributes for the job item.
        defaults: function() {
            return {
                title: "empty job ID...",
                order: Jobs.nextOrder(),
                done: false
            };
        },
        // Toggle the `done` state of this job item.
        toggle: function() {
            this.save({done: !this.get("done")});
        }

    });

    // Job Collection
    // ---------------

    // The collection of jobs is backed by *localStorage* instead of a remote
    // server.
    var JobList = Backbone.Collection.extend({
        // Reference to this collection's model.
        model: Job,
        // Save all of the job items under the `"jobs-backbone"` namespace.
        localStorage: new Backbone.LocalStorage("jobs-backbone"),
        // Filter down the list of all job items that are finished.
        done: function() {
            return this.where({done: true});
        },
        // Filter down the list to only job items that are still not finished.
        remaining: function() {
            return this.where({done: false});
        },
        // We keep the Jobs in sequential order, despite being saved by unordered
        // GUID in the database. This generates the next order number for new items.
        nextOrder: function() {
            if (!this.length)
                return 1;
            return this.last().get('order') + 1;
        },
        // Jobs are sorted by their original insertion order.
        comparator: 'order'

    });

    // Create our global collection of **Jobs**.
    var Jobs = new JobList;

    // Job Item View
    // --------------

    // The DOM element for a job item...
    var JobView = Backbone.View.extend({
        //... is a list tag.
        tagName: "li",
        // Cache the template function for a single item.
        template: _.template($('#item-template').html()),
        // The DOM events specific to an item.
        events: {
            "click .toggle": "toggleDone",
            "dblclick .view": "edit",
            "click a.destroy": "clear",
            "keypress .edit": "updateOnEnter",
            "blur .edit": "close"
        },
        // The JobView listens for changes to its model, re-rendering. Since there's
        // a one-to-one correspondence between a **Job** and a **JobView** in this
        // app, we set a direct reference on the model for convenience.
        initialize: function() {
            this.listenTo(this.model, 'change', this.render);
            this.listenTo(this.model, 'destroy', this.remove);
        },
        // Re-render the titles of the job item.
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            this.$el.toggleClass('done', this.model.get('done'));
            this.input = this.$('.edit');
            return this;
        },
        // Toggle the `"done"` state of the model.
        toggleDone: function() {
            this.model.toggle();
        },
        // Switch this view into `"editing"` mode, displaying the input field.
        edit: function() {
            this.$el.addClass("editing");
            this.input.focus();
        },
        // Close the `"editing"` mode, saving changes to the job.
        close: function() {
            var value = this.input.val();
            if (!value) {
                this.clear();
            } else {
                this.model.save({title: value});
                this.$el.removeClass("editing");
            }
        },
        // If you hit `enter`, we're through editing the item.
        updateOnEnter: function(e) {
            if (e.keyCode === 13)
                this.close();
        },
        // Remove the item, destroy the model.
        clear: function() {
            this.model.destroy();
        }

    });

    // The Application
    // ---------------

    // Our overall **AppView** is the top-level piece of UI.
    var AppView = Backbone.View.extend({
        // Instead of generating a new element, bind to the existing skeleton of
        // the App already present in the HTML.
        el: $("#jobapp"),
        // Our template for the line of statistics at the bottom of the app.
        statsTemplate: _.template($('#stats-template').html()),
        // Delegated events for creating new items, and clearing completed ones.
        events: {
            "keypress #new-job": "createOnEnter",
            "click #clear-completed": "clearCompleted",
            "click #toggle-all": "toggleAllComplete"
        },
        // At initialization we bind to the relevant events on the `Jobs`
        // collection, when items are added or changed. Kick things off by
        // loading any preexisting jobs that might be saved in *localStorage*.
        initialize: function() {

            this.input = this.$("#new-job");
            this.allCheckbox = this.$("#toggle-all")[0];

            this.listenTo(Jobs, 'add', this.addOne);
            this.listenTo(Jobs, 'reset', this.addAll);
            this.listenTo(Jobs, 'all', this.render);

            this.footer = this.$('footer');
            this.main = $('#main');

            Jobs.fetch();
        },
        // Re-rendering the App just means refreshing the statistics -- the rest
        // of the app doesn't change.
        render: function() {
            var done = Jobs.done().length;
            var remaining = Jobs.remaining().length;

            if (Jobs.length) {
                this.main.show();
                this.footer.show();
                this.footer.html(this.statsTemplate({done: done, remaining: remaining}));
            } else {
                this.main.hide();
                this.footer.hide();
            }

            this.allCheckbox.checked = !remaining;
        },
        // Add a single job item to the list by creating a view for it, and
        // appending its element to the `<ul>`.
        addOne: function(job) {
            var view = new JobView({model: job});
            this.$("#job-list").append(view.render().el);
        },
        // Add all items in the **Jobs** collection at once.
        addAll: function() {
            Jobs.each(this.addOne, this);
        },
        // If you hit return in the main input field, create new **Job** model,
        // persisting it to *localStorage*.
        createOnEnter: function(e) {
            if (e.keyCode !== 13)
                return;
            if (!this.input.val())
                return;

            Jobs.create({title: this.input.val()});
            this.input.val('');
        },
        // Clear all done job items, destroying their models.
        clearCompleted: function() {
            _.invoke(Jobs.done(), 'destroy');
            return false;
        },
        toggleAllComplete: function() {
            var done = this.allCheckbox.checked;
            Jobs.each(function(job) {
                job.save({'done': done});
            });
        }

    });

    // Finally, we kick things off by creating the **App**.
    var App = new AppView;

});

HTML正文:

<div id="jobapp">
            <header>
                <h1>Jobs</h1>
                <input id="new-job" type="text" placeholder="Enter a Job ID?">
            </header>
            <section id="main">
                <input id="toggle-all" type="checkbox">
                <label for="toggle-all">Mark all as complete</label>
                <ul id="job-list"></ul>
            </section>
            <footer>
                <a id="clear-completed">Clear completed</a>
                <div id="job-count"></div>
            </footer>
        </div>

        <div id="instructions">
            Double-click to edit a job ID.
        </div>

        <script src="json2.js"></script>
        <script src="jquery.js"></script>
        <script src="underscore.js"></script>
        <script src="backbone.js"></script>
        <script src="backbone.localStorage.js"></script>
        <script src="jobs.js"></script>

        <!-- Templates -->

        <script type="text/template" id="item-template">
            <div class="view">
            <input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
            <label><%- title %></label>
            <a class="destroy"></a>
            </div>
            <input class="edit" type="text" value="<%- title %>" />
        </script>

        <script type="text/template" id="stats-template">
            <% if (done) { %>
            <a id="clear-completed">Clear <%= done %> completed <%= done == 1 ? 'item' : 'items' %></a>
            <% } %>
            <div class="job-count"><b><%= remaining %></b> <%= remaining == 1 ? 'item' : 'items' %> left</div>
        </script>

CSS:

html,
body {
    margin: 0;
    padding: 0;
}

body {
    font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
    line-height: 1.4em;
    background: #eeeeee;
    color: #333333;
    width: 520px;
    margin: 0 auto;
    -webkit-font-smoothing: antialiased;
}

#jobapp {
    background: #fff;
    padding: 20px;
    margin-bottom: 40px;
    -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
    -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
    -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
    -o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
    box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
    -webkit-border-radius: 0 0 5px 5px;
    -moz-border-radius: 0 0 5px 5px;
    -ms-border-radius: 0 0 5px 5px;
    -o-border-radius: 0 0 5px 5px;
    border-radius: 0 0 5px 5px;
}

#jobapp h1 {
    font-size: 36px;
    font-weight: bold;
    text-align: center;
    padding: 0 0 10px 0;
}

#jobapp input[type="text"] {
    width: 466px;
    font-size: 24px;
    font-family: inherit;
    line-height: 1.4em;
    border: 0;
    outline: none;
    padding: 6px;
    border: 1px solid #999999;
    -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
    -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
    -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
    -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
    box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}

#jobapp input::-webkit-input-placeholder {
    font-style: italic;
}

#main {
    display: none;
}

#job-list {
    margin: 10px 0;
    padding: 0;
    list-style: none;
}

#job-list li {
    padding: 18px 20px 18px 0;
    position: relative;
    font-size: 24px;
    border-bottom: 1px solid #cccccc;
}

#job-list li:last-child {
    border-bottom: none;
}

#job-list li.done label {
    color: #777777;
    text-decoration: line-through;
}

#job-list .destroy {
    position: absolute;
    right: 5px;
    top: 20px;
    display: none;
    cursor: pointer;
    width: 20px;
    height: 20px;
    background: url(destroy.png) no-repeat;
}

#job-list li:hover .destroy {
    display: block;
}

#job-list .destroy:hover {
    background-position: 0 -20px;
}

#job-list li.editing {
    border-bottom: none;
    margin-top: -1px;
    padding: 0;
}

#job-list li.editing:last-child {
    margin-bottom: -1px;
}

#job-list li.editing .edit {
    display: block;
    width: 444px;
    padding: 13px 15px 14px 20px;
    margin: 0;
}

#job-list li.editing .view {
    display: none;
}

#job-list li .view label {
    word-break: break-word;
}

#job-list li .edit {
    display: none;
}

#jobapp footer {
    display: none;
    margin: 0 -20px -20px -20px;
    overflow: hidden;
    color: #555555;
    background: #f4fce8;
    border-top: 1px solid #ededed;
    padding: 0 20px;
    line-height: 37px;
    -webkit-border-radius: 0 0 5px 5px;
    -moz-border-radius: 0 0 5px 5px;
    -ms-border-radius: 0 0 5px 5px;
    -o-border-radius: 0 0 5px 5px;
    border-radius: 0 0 5px 5px;
}

#clear-completed {
    float: right;
    line-height: 20px;
    text-decoration: none;
    background: rgba(0, 0, 0, 0.1);
    color: #555555;
    font-size: 11px;
    margin-top: 8px;
    margin-bottom: 8px;
    padding: 0 10px 1px;
    cursor: pointer;
    -webkit-border-radius: 12px;
    -moz-border-radius: 12px;
    -ms-border-radius: 12px;
    -o-border-radius: 12px;
    border-radius: 12px;
    -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
    -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
    -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
    -o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
    box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
}

#clear-completed:hover {
    background: rgba(0, 0, 0, 0.15);
    -webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
    -moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
    -ms-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
    -o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
    box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
}

#clear-completed:active {
    position: relative;
    top: 1px;
}

#job-count span {
    font-weight: bold;
}

#instructions {
    margin: 10px auto;
    color: #777777;
    text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
    text-align: center;
}

#instructions a {
    color: #336699;
}

#credits {
    margin: 30px auto;
    color: #999;
    text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
    text-align: center;
}

#credits a {
    color: #888;
}

可以从我的网站libs

中获取相关性

我的网站上的工作版本为here