Preliminary study on Backbone

Source: Internet
Author: User
Tags addall tojson

Original address: http://www.cnblogs.com/yexiaochai/archive/2013/07/27/3219402.html

Objective

Finally to the weekend, after the transition of the long-HTML5 work finally implemented, the mobile front-end, so really into the development of the era.

This Monday began to enter the job, came to find really like the countryside came to the city, a lot of things do not understand, but also to implement the problem of renting, life work screwed to a lump.

Because the last time to go to Henan to toss a few, the economy is also bright red, so the first week a bit of the feeling of a muddle, have not done anything on the end.

New team of people feel a bit vigorous, old colleagues completely no pressure, another new colleague adapt quickly, incredibly can enter the framework of development, is this really so many masters? Small side, Alexander.

Now the project is using Jquery+requirejs+backbone, the first two days we learned a little bit about the next requirejs, to say good familiar with pure nonsense, but there is a general impression of it.

Our task today is to learn some backbone, and so familiar to the next day to string up the few guys to try, because there will be a task in Tuesday, do not try to wait for the belch fart.

Backbone Introduction

Chinese api:http://www.csser.com/tools/backbone/backbone.js.html

English api:http://backbonejs.org/

Backbone is an excellent class library for building JavaScript applications. He is concise, lightweight and functional.

Backbone uses the MVC pattern, which itself provides models, controllers, and views so that the skeleton of our application is formed.

Backbone relies on underscore, a class library that provides more than 60 functions for manipulating array operations, function bindings, and JavaScript templating mechanisms.

So let's take a look at some good friends:

With a preliminary impression, let's take a look at him and do some God-made horses.

Model

The model is where the application data is stored. We can think of the model as a careful abstraction of the application's raw data, and add some tool functions and events.

We can use Backbone.model's Extend method to create a backbone model:

var User = Backbone.Model.extend ({    initialize:function () {}});

The first parameter of extend is an object, which becomes the attribute of the model instance;

The second parameter is the hash of the optional class property, which can be generated by calling extend multiple times to generate subclasses of the model, and they inherit all of the Father's class and instance properties:

var User = Backbone.Model.extend ({    //instance attribute    instanceproperty: ' foo '}, {//    class attribute    classproperty: ' Bar '}); Assertequal (User.instanceproperty, ' foo '); assertequal (User.classproperty, ' Bar ');

When the model is instantiated, his initialize method can accept arbitrary instance parameters, which works because the backbone model itself is a constructor, so you can use new to generate an instance:

var User = Backbone.Model.extend ({    initialize:function (name) {        this.set ({name:name});}    }); var user = new User (' Sword fetish '); Assertequal (User.get (' name '), ' sword fetish ');

Ps:assertequal judgment equals

Models and properties

Use the set and Get methods to set properties for an instance:

var user = new User (); User.set ({name: ' leaf message '}); User.get (' name '); Leaves Chai user.attributes;//{name: ' Leaf-chai '}

We see in fact that User.arributes is an object literal, and we do not directly manipulate him because we use the Get/set method to conduct our validation process.

We use the Validate method to validate an instance property without any validation by default, if we need to verify:

var User = Backbone.Model.extend ({    validate:function (attr) {        if (!attr.name | | Attr.name.length < 3) {            re Turn ' name length too short ';        }}    });

If the property is valid, validate will not be able to ignore it, and the error string may be returned by the wrong object, and the Get/set method will trigger the error event if the validation fails:

var user = new User (), User.bind (' Error ', function (model, error) {    //error handling}), User.set ({name: ' 0 '});//Add an error handler to a specific collection User.set ({name: ' 0 '}, {error:function (model, error) {}});

Specify default properties using an object with the hash name defaults, and any property that does not have a value specified will be set to the default value when an instance model is created:

var chat = Backbone.Model.extend ({    defaults: {name: ' Leaf Message '}}); Assertequal ((New Chat). Get (' name '), ' leaf-chai ');
Collection

In backbone, the data for a model instance is stored in multiple collections, and the reason why a separate collection is used between models is a bit complicated, but in practice we often do so (although I haven't done it yet).

For example, creating a Twitter requires two collections followers and Followees, both of which have a user instance populated with data, although both collections come from the same model, but each contains a different array of instances, thus independently forming the collection.

For models, you can create a collection by extending backbone.collection:

var Users = Backbone.Collection.extend ({    model:user});

In the example above, we override the Model property to specify the models associated with the collection (here is the user model), although this step is not required, but setting a default model point for the collection can often be useful.

Typically, a collection contains one instance of a single model, not multiple instances of different models.

When creating a collection, you can pass an array of models, such as the backbone model, if an initialization instance function is defined, which is called when it is initialized:

var users = new users ([{name: ' Leaf message '}, {name: ' Vegetarian is true '}]);

Another way is to add a model to the collection using the Add method:

Users.add ({name: ' leaf message '}); Users.add ([{name: ' Leaf message '}, {name: ' Vegetarian is true '}]);

When you add a model to a collection, the Add event is triggered:

Users.bind (' Add ', function (user) {//    ...}); /Remove a model users.bind (' Remove ', function (user) {    //...}); /Get model VAR based on model ID user = Users.get (' ModuleID ');//Set the model is modified after the Change event var user = New User ({name: ' leaf message '}); var users = new back Bone. Collection (); Users.bind (' Change ', function (REC) {//changing a record}); Users.add (user); User.set ({name; ' Vegetarian is true '});
Control the internal order of the collection

The order of the elements within a set can be controlled by the comparator method, which is the rule that you want the collection to sort internally:

var Users = Backbone.Collection.extend ({    comparator:function (user) {        return user.get (' name ');    }});

The return value can be a value or a number, for example we'll have a chance to try it next time.

View

The backbone view is not a template, but rather a control class that handles the performance of the model.

In many MVC views generally refer to HTML or templates, they handle events and rendering in the controller, but in backbone view:

The view represents a block of UI logic that is responsible for a simple DOM content
var Userview = Backbone.View.extend ({    initialize:function () {},    render:function () {}});

Regardless of whether the view is inserted into the page, each view knows the current DOM element, that is, This.el,el is an element created from attributes such as the view's tagname, classname, or ID, and no such value El is an empty div:

var Userview = Backbone.View.extend ({    tagName: ' span ',    className: ' Users '}), var userview = new Userview ();// <span class= "Users" ></span>

If you want the view to be bound to an element that already exists on the page, specify the El directly (you must load the page before you can specify it, or you cannot find it):

var Userview = Backbone.View.extend ({    el: $ ('. Usets ')});//You can also instantiate a view when passing El (TagName, Classname\id) New Userview ({ID : ' ID '});
Render View

Each view has a render method, and by default there is no action, and the Render method is called once the view needs to be redrawn, and different views override the function with functions of different functions to handle template rendering and update El with new HTML:

var Todoview = Backbone.View.extend ({    Template: _.template ($ (' #tmpt '). html ()),    render:function () {        $ ( this.el). HTML (This.template (This.model.toJSON ()));        return this;    });

Backbone itself does not know how we render the view, we can produce our own elements can also use the template class library (usually with this).

In the previous code, we used the local property of This.model, which pointed to a model instance that was passed to the view when instantiated, and the model's Tojson method actually returned the original property when the model was unprocessed, which can be used in the template:

New Todoview ({model:new Todo});
Delegate Events

With delegates, backbone's view provides a quick and easy way to add events to El:

var Todoview = Backbone.View.extend ({    events: {        ' change Input[type=checkbox] ': ' Toggledone ',        ' click. Destroy ': ' Clear '    },    toggoledone:function () {},    clear; function () {}});

The events object is {' EventType selector ': ' Callback '} in this format, selector is optional and does not provide a binding value on El.

The delegate takes advantage of the event bubbling mechanism, meaning it can be triggered all the time regardless of whether the El content changes (estimated to resemble delegate bar).

When the above callback event is triggered, his context is the view currently on the afternoon, so the this.model/el in this can be used.

Bindings and contexts

In fact, whenever the model of the view changes, the change event is triggered, and then the function is called, which means that the view and HTML of the application are synchronized with the corresponding model data.

var Todoview = Backbone.View.extend ({    initialize:function () {        _.bindall (this, ' render ', ' close ');        This.model.bind (' Change ', this.render);    },    close:function () {}});

Be aware that the context in the callback function has changed, and underscore provides a function:

_.bindall (context, func);

He binds the function name to a context, and bindall guarantees that all the given functions are always called in the specified context, since the function context is always randomly changing, which is useful.

Model destruction requires a view-bound delete event, which is triggered when the El is removed:

var Todoview = Backbone.View.extend ({    initialize:function () {        _.bindall (this, ' render ', ' close ');        This.model.bind (' Change ', this.render);        This.model.bind (' delete ', this.remove);    },    Remove:function () {$ (This.el). Remove ()});
Controller

The backbone Controller associates the state of the application with the hash fragment of the URL, making the URL address shareable or used as a bookmark.

Essentially, a controller is a number of routes and functions that are called when navigating to these routes:

Routes: "Help    ": ' Help ',//#help    ' search/:query ': ' Search ',//#search/kiwis    ' search/:query/p:page ': ' Search ',//#search/kiwis/p7    ' file/*peth ': ' File '//#file/any/path.txt}

The argument starts with ":" and then the parameter name, and when the route is called, all parameters are passed to his function, * for wildcards, and for parameter one to be passed to the routed function along with the matching values.

Routes are parsed in the order in which they are defined in the hash object, to create a controller:

var Pagecontroller = Backbone.Controller.extend ({    routes: "Help"        : ' Help ',//#help        ' search/:query ': ' Search ',//#search/kiwis        ' search/:query/p:page ': ' Search ',//#search/kiwis/p7        ' file/*peth ': ' File '//#file/ Any/path.txt    },    index:function () {},    help:function () {},    search:function () {}});

When the user is navigated to "Http://....com#search/param", the search function is invoked regardless of whether the hand is lost or backward, and its arguments are passed Param

If you want Ajax and SEO more friendly, the route prefix must be "!/", while the server side also need to make a bit of adjustment.

Server synchronization

By default, the model changes (saves), and Backbone uses AJAX and server communication (Backbone.sync) to successfully update the client model.

To use this property, you need to define the URL, and on the server side processing the rest form request, backbone will handle the remaining tasks:

var User = Backbone.Model.extend ({    URL: '/users '});

The URL can be either a string or a function return string, backbone and delete to change several function mapping:

Create = Post/collectionread = Get/collection[/id]update = Put/collection/iddelete = Delete/collection /id

For example, to create a user instance, backbone sends a POST request/uesrs, updates a user instance, sends it to the/USERS/ID node, and returns a JSON-formatted object when the server responds

If you want to use the Save (attr, option) function to save the model to the server, you can arbitrarily pass a hash object consisting of a property and a request item, if the model has an ID, if the model exists on the server, the presence is a put request, or the POST request adds data:

var user = new User (); User.set ({name: ' leaf message '}); User.save (null, {    success:function () {        //Save succeeded    }});

All of the Save is asynchronous, with success or failure listening for Ajax callbacks, which we typically share with jquery.

Populating collections

We already know how to create/update the model, but how do we get the model data for the first time?

This is why the backbone collection occurs, they are used to request remote data and are saved locally, similar to the model, a collection must be assigned a URL to set its data source, and if not, the model URL associated with it is used by default:

var followers = Backbone.Collection.extend ({    model:user,    url: '/user '}),//fetch is used to refresh the model, the function requests data, If the remote data is inconsistent with the current model, the Change event Followers.fetch () will be triggered;

The FETCH function of the collection will send a get-request-Path server, get remote data, and finally refresh the collection to trigger the Refresh event.

You can use the Refresh function to manually refresh the collection, passing in a model object, the first time you set up the page with this method is very convenient, here and the page loaded after the Send GET request is not the same, we can pass the JSON object to refresh, and pre-populated into the collection, such as:

Users.refresh ({name; ‘‘});
Custom behavior

The Backbone.sync method is called when the backbone view reads or saves the model to the server, and we can override the method to change its default behavior (in XML, local storage):

/*method is the Model Options request option that the Crud method (create, read, update, delete) models needs to save, including the success failure function */backbone.sync = function (method, Model, Options) {    options.success (model);};

Each model or collection can only cover its own sync function.

Let's look at an example of an extended HTML5 local storage:

All pending items are saved to the local storage namespace "todos" Toto.prototype.localStorage = new Store (' Todos ');//Override Backbone.syncBackbone.sync = function (method, model, options) {    var resp, store = Model.localstorage | | model.collection.localStorage;    Switch (method) {case        ' read ': resp = model.id? Store.find (model): Store.findall ();        Case ' Create ': RESP = store.create (model); break;        Case ' Update ': RESP = store.update (model); break;        Case ' Delete ': resp = Store.destroy (model); break;    }    if (resp) {        options.success (resp);    } else {        options.error (' not find ');}    }
Simple Combat-Official edition

First, let's take a look at an official example:

Specific code you can go to download, which used a lot of class library We also temporarily do not care about it, we will try to do now.

This is a simple to-do list application, we would like to be able to do additions and deletions to change the operation, after the page refresh can still maintain data.

Page structure (CORE)

 1 

The page structure is simple and its core is:

A text box (#new-todo) to create a new to-do

A list (#todo-list) to show

Here is the basic TODO model, which has the content and done properties, while providing the toggle method to set the Done property:

Todo is the meaning of the memo oh var Toto = Backbone.Model.extend ({    defaults: {        done:false    },    toggle:function () {        Settings do not do a click, the settings do not click on the        ... This.save ({done:!this.get (' Done ')});}    );

Then we define a Todo collection and also the place to save the TODO model:

var todolist = Backbone.Collection.extend ({    Model:todo,    localstorage:new store (' Todos '),//all items saved to Todos namespace    //filter completed Items    done:function () {        return this.filter (function (TODO) {            return todo.get (' done ');        });    },    remaining:function () {        return This.without.applay (this, this.done);    }}); var Todos = new ToDoList ();

Because this is local storage, we introduced Backbone.localstorage, and the next step is to show the view

 1 var todoview = Backbone.View.extend ({2 tagName: ' Li ',///view-by-Li Tags 3 template: $ (' #item-template '). Template (), Get Template 4 Events: {5 ' Change. Check ': ' Toggledone ', 6 ' DblClick. Todo-content ': ' Edit ', 7 ' cl     Ick. Todo-destroy ': ' Destroy ', 8 ' keypress. Todo-input ': ' Updateonenter ', 9 ' blur. Todo-input ': ' Close ' 10         },11 initialize:function () {12//ensure the correct scope of the _.bindall (this, ' render ', ' close ', ' remove '); 14 Monitor storage template modifications to determine whether to modify El15 this.model.bind (' Change ', This.render); This.model.bind (' Destroy ', This.render );},18 render:function () {19//Use storage template update el20 var el = Jquery.tmpl (This.template, this.model.to JSON ()); $ (this.el). html (EL); return this;23},24 tiggledone:function () {This.mod     El.toggle ();},27 edit:function () {$ (This.el). addclass (' editing '); This.input.focus (); 30 },31 Close:function () {//Turn off screenwriter status This.model.save ({Content:this.input.val ()}); $ (this.el). Removeclass (' editing '); 34 },35//press ENTER to end edit Updateonenter:function (e) {PNS if (E.keycode = =) E.target.blur () ;},40 Remove:function () {$ (This.el). Remove ();},43 destroy:function () . Model.destroy (); 45}46});

We entrust the blood multiple events to the admin update, complete and delete the Todo view, such as whenever the check box changes Toggledone is called, and the Done property is toggled, and finally the change event is triggered, causing the view to re-render.

Take a look at our 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 <%= Did%> completed <%= done = = 1? ' Item ': ' Items '%></a><%}%><div class= "Todo-count" ><b><%= remaining%></b> <%= remaining = = 1? ' Item ': ' Items '%> left</div></script>

PS: I have written about the idea here, there are inconsistencies in the places you can see.

Finally we come to an end:

1 var appview = Backbone.View.extend ({2     el: # (' #todoapp '),//bound to existing skeleton 3     events: {4         ' keypress #new-todo ': ' CRE Ateonenter ', 5         ' click. Todo-clear a ': ' clearcompleted ' 6     }, 7/     * 8     when initializing, bind related events to the Todos collection, When an event is triggered when an element in the collection is added or modified, 9     initializes the data by loading records that may exist in the local store     */11     initailize:function () {         _.bindall (this, ' AddOne ', ' addall ', ' render '),         this.input = this.$ (' #new-todo ');         todos.bind (' Add ', this.addone); 15         todos.bind (' Refresh ', this.addall);         Todos.fetch ();     },18     addone:function (todo) {         var view = new Todoview ({Model:todo});         this.$ (' #todo-list '). Append (View.render (). EL);     },22     //... ); var App = new Appview ();

When the page loads for the first time, the Todos collection populates the data, then triggers the Refresh event, investigates the AddAll to get the TODO model, generates Todoview views, and adds them to #todo-list.

When a new TODO model is added to Todos, the Add event is triggered and the addone is called to make the last view update.

Brief summary

At this point, we stumbled on the example of the Generals network, I do not know you buy it??

Anyway, I don't buy it, because I feel a little confused, so let's write an example to try it out.

Simple Combat-demo

Continue later ...

Conclusion

Well, the first stage of our study basically ended, which is not a practical example of the case I later, so we should have a preliminary understanding of the backbone

Tomorrow our task is to combine Requirejs in backbone do a little bit of practice, so we can say that we are proficient in requirejs in the backbone ...

Add

Just here to see a few good pictures, to paste it out:

Original Backbone Source Analysis-backbone Architecture + flowchart

Preliminary study on Backbone

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.