我正在尝试使用骨干从集合中获取特定项目。我正在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'
答案 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