Model
This is basically the part of the view. Now let's talk about the model.
The model is actually a data record. However, it is not a general static data record. It not only does not limit the data structure, but also can automatically interact with the backend, or even bind events to automatically update the corresponding view.
The simplest model is as follows:
VaR Foo = backbone. model. extend ({}); // or initialize the default data var Foo = backbone. model. extend ({defaults: {name: "hello", value: "233"}); // or assign a value at runtime. // For example, VAR Foo = new Foo ({name: "world", value: "874"}); // or var Foo = new Foo; Foo. set ({name: "world", value: "874 "});
You can display the result to see the effect:
$("#body").text(JSON.stringify(foo.toJSON()));
Collection
Collection is a set of models. Because model is a data record, that is, collection is equivalent to a dataset.
Similarly, a simple collection is as follows:
var FooList = Backbone.Collection.extend({ model: Foo});
Then you can add data:
var foos = new FooList; foos.add([{name:"hello", value:"233"},{name:"world", value:"874"}]); $("#body").text(JSON.stringify(foos.at(0)));
For more information about how to update and delete data, see the official documentation.
Note that each model record automatically has an ID/CID attribute, which is the unique identifier of the record. For example:
foos.get(foos.at(0).cid)
Model event binding
In order to update the display on the view in a timely manner after data changes, the event mechanism should be used for processing.
var Task = Backbone.Model.extend({ initialize: function () { this.on("change:name", function (model) { alert("new name is : " + model.get("name")); }); }}); var t = new Task({tid:"3333", name:"oooo", state:"working"}); t.set({name:"xxx"});
When T. Set () is executed, the change: Name event is triggered when the model data changes.
Backend for testing
Before talking about the interaction with the backend, let's start with a simple backend.
Here we use web. py for the simplest:
# start.pyimport webweb.config.debug = Falsefrom webpyext.webcommon import WebNotfoundErrorfrom webpyext.apiserver import RestBaseHandler, kwargs_decoratorimport logginglogger = logging.getLogger(__name__)urls = ( "/task/?" , "Tasks", "/task/([0-9]+)/?" , "Tasks", )app = web.application(urls, locals())class APIHandler(RestBaseHandler): def __init__(self): self.dbconn = web.database(dbn='sqlite', db='xllxweb.dat')class Tasks(APIHandler): def GET_(self, id=""): if id: result=self.dbconn.select("task", where="id=$id", vars={'id':int(id)}).list() if not len(result): raise WebNotfoundError("This task was not found!") return result[0] else: return self.dbconn.select("task").list() @kwargs_decorator def POST_(self, kwargs={}): return "%s" % self.dbconn.insert("task", **kwargs) @kwargs_decorator def PUT_(self, id, kwargs={}): self.dbconn.update("task", where="id=$id", vars={'id':id}, **kwargs) return "" def DELETE_(self, id): self.dbconn.delete("task", where="id=$id", vars={'id':id}) return ""if __name__ == "__main__": import logging logging.basicConfig(level=logging.DEBUG) dbconn = web.database(dbn='sqlite', db='xllxweb.dat') sql = """create table if not exists task ( id integer primary key not null, name varchar not null, state varchar )""" dbconn.query(sql) app.run()
Specifically, webpyext is a self-written tool library that extends Web. py and provides some enhancements. For example, three things are used here: restbasehandler, kwargs_decorator, and webnotfounderror.
Among them, restbasehandler provides a unified route handler to process API calls and converts a fixed format rest API call request to a method call, which also includes JSON conversion of returned data. Kwargs_decorator is used to convert HTTP request parameters into kwargs parameters in method calls. It can automatically process backbone JSON-format requests (not standard HTTP requests ). Webnotfounderror is one of the HTTP Response-specific exceptions.
In this example, an SQLite Database: xllxweb. dat is used for testing. Only one table is included: task. For the table structure, see the code.
Now these functions are implemented in the background:
/Task: Get all tasks (get) or create a new task (post, with the parameter as the task field, return the record ID)
/Task/[: TID]: Get the task (get) or modify (put, the parameter is the field to be modified) or delete (delete, no parameter) of a taskid)
The above is fully implemented according to the requirements of backbone and complies with the rest specifications.
Run Python start. py to access Python through http: // localhost: 8080.
Interaction between model/collection and backend
First, write the corresponding model and collection:
var Task = Backbone.Model.extend({ urlRoot: "/task",});var TaskList = Backbone.Collection.extend({ url: "/task", model: Task,});
This is the simplest implementation. Compared with the previous example, URL/urlroot is added, which is the organ that interacts with the backend.
Then you can perform the CRUD operation on this basis.
// Createvar t = new Task({name:"hello", state:"waiting"});t.save();alert("Saved");var tid = t.id// Readt = new Task({id:tid});t.fetch({success: function(task) { alert(JSON.stringify(task.toJSON()));}});// Updatet = new Task({id:tid});t.set({name:"world"});t.save();alert("Updated");// Deletet = new Task({id:tid});t.destroy();
Note that all these operations areAsynchronousTo obtain the operation result (such as the read operation), you must use the callback function (such as the success callback in fetch ), otherwise, you will not be able to obtain the correct results (for example, if you read the T variable value immediately after fetch execution, there will be only one id value, and other attribute values will be empty ). The alert inserted in the Code is mainly used for waiting.
The above is the model operation method, and collection is similar, the difference is that the collection gets a set of model lists.
The HTTP request and response formats for the preceding operations are as follows:
|
Model Request |
Model response |
Collection Request |
Collection response |
Create |
Post/task/ Content-Type: Application/JSON {TID: "1234 "...} |
... |
No |
No |
Read |
GET/task/1 |
{TID: "1234 "...} |
GET/task/ |
[{TID: "1234"...}...] |
Update |
Put/task/1 Content-Type: Application/JSON {Name: "world "...} |
... |
No |
No |
Delete |
Delete/task/1 |
... |
No |
No |
The table above is for reference during backend development. If you encounter any problems during development, we recommend that you enable the firebug analysis immediately.
Among them, the collection only has read, and other create/update/delete operations are actually processed by calling the corresponding method of model.
Data validation for Model
To prevent incorrect values from being stored in the model, you can add a validation check to it, similar to the database's "constraint )".
The following Code restricts that the name field must be longer than three characters.
var Task = Backbone.Model.extend({ urlRoot: "/task", initialize: function () { this.on("invalid", function (model, error) { alert(error); }); }, validate: function (attrs, options) { if (attrs.name.length<3) { return "name must longer than 3 chars!"; } },});var t = new Task({id:1});t.fetch({success: function (task) { task.set({name:"hi"}); task.save(); }});
Note that backbone has a pitfall setting, that is, if a field set is null, for example, set ({name: ""}), The validate verification will not be triggered, be careful when using this vulnerability.
In addition, there is also a pitfall: in the current version (0.9.10) I am using, validate is only triggered when saving, A lot of information on the Internet says that it may trigger settings of previous versions during set, so be careful with this pitfall.
(To be continued)