Backbone.js,用来构建JavaScript项目的框架。官方给的介绍:

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions,views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

可以看到,连官方都没有自称自己是MVC框架,充其量只是一个MV框架。作为一款轻量级的JavaScript框架系统,Backbone.js非常简单,容易学习容易操作,但是也相对应的有很严重的问题。我们就一个个来看一下。

主页:http://backbonejs.org/

github:https://github.com/jashkenas/backbone

Tutorial:http://backbonetutorials.com/

学习一个新的东西,一般你都会从官方文档开始,而backbone.js的文档实在是让我眼前一亮,这TM是文档?这根本就是一个API列表,谢谢。于是乎只能在网上找tutorial,所幸还是有一个不错的站点,给出了backbone.js的教程。接下来我们就按backbone.js的主要组件的结构来分析下backbone.js。

Model

官方对于Model的定义:

Models are the heart of any JavaScript application, containing the interactive data as well as a large part of the logic surrounding it: conversions, validations, computed properties, and access control.

Backbone.js里的Model就是数据模型,它提供了你业务逻辑上必须的数据存储的需求。包括了:

  • 数据模型的定义:含初始化
  • 数据存储:含数据更改(get、set)
  • 监听数据变化:在模型内数据有变化的时候响应事件(比如说:更新数据对应的UI)
  • 与服务器交互:在模型内设定该模型绑定的RESTful地址,并进行数据的提交或更新

给几段代码:

[codesyntax lang="javascript"]

    Person = Backbone.Model.extend({
    defaults: {
        name: 'Fetus',
        age: 0,
        child: ''
    },
    initialize: function(){
        alert("Welcome to this world");
    }
});

var person = new Person({ name: "Thomas", age: 67, child: 'Ryan'});

var age = person.get("age"); // 67
var name = person.get("name"); // "Thomas"
var child = person.get("child"); // 'Ryan'

[/codesyntax]

[codesyntax lang="javascript"]

    var UserModel = Backbone.Model.extend({
    urlRoot: '/user',
    defaults: {
        name: '',
        email: ''
    }
});
var user = new Usermodel();
// Notice that we haven't set an `id`
var userDetails = {
    name: 'Thomas',
    email: '[email protected]'
};
// Because we have not set a `id` the server will call
// POST /user with a payload of {name:'Thomas', email: '[email protected]'}
// The server should save the data and return a response containing the new `id`
user.save(userDetails, {
    success: function (user) {
        alert(user.toJSON());
    }
})
// Here we have set the `id` of the model
var user = new Usermodel({
    id: 1,
    name: 'Thomas',
    email: '[email protected]'
});

// Let's change the name and update the server
// Because there is `id` present, Backbone.js will fire
// PUT /user/1 with a payload of `{name: 'Davis', email: '[email protected]'}`
user.save({name: 'Davis'}, {
    success: function (model) {
        alert(user.toJSON());
    }
});

[/codesyntax]

View

官方对于View的定义:

Backbone views are used to reflect what your applications' data models look like. They are also used to listen to events and react accordingly. This tutorial will not be addressing how to bind models and collections to views but will focus on view functionality and how to use views with a JavaScript templating library, specificallyUnderscore.js's _.template.

简而言之Backbone.js的View即负责显示,又负责事件的监听和反应。(这真的是view么?!)

View的功能点包含了:

  • 可重用的模板代码
  • HTML元素事件的绑定监听
  • HTML页面代码的渲染

简单来说,其工作的流程可以是:

  • 在页面上引入可重用的模板代码
  • 在页面上加入自定义id的div元素,作为渲染输出的父节点
  • 编写JavaScript代码,将HTML事件绑定到View对象中,并编写render函数渲染HTML页面

给几段代码:

[codesyntax lang="javascript"]

<script type="text/template" id="search_template">
    <!-- Access template variables with <%= %> -->
    <label><%= search_label %></label>
    <input type="text" id="search_input" />
    <input type="button" id="search_button" value="Search" />
</script>

<div id="search_container"></div>

<script type="text/javascript">
     SearchView = Backbone.View.extend({
        initialize: function(){
            this.render();
        },
        render: function(){
            //Pass variables in using Underscore.js Template
            var variables = { search_label: "My Search" };
            // Compile the template using underscore
            var template = _.template( $("#search_template").html(), variables );
            // Load the compiled HTML into the Backbone "el"
            this.$el.html( template );
        },
        events: {
            "click input[type=button]": "doSearch"  
        },
        doSearch: function( event ){
            // Button clicked, you can access the element that was clicked with event.currentTarget
            alert( "Search for " + $("#search_input").val() );
        }
    });

    var search_view = new SearchView({ el: $("#search_container") });
</script>

[/codesyntax]

Collection

官方的说明:

Backbone collections are simply an ordered set of models. Such that it can be used in situations such as;

  • Model: Student, Collection: ClassStudents
  • Model: Todo Item, Collection: Todo List
  • Model: Animal, Collection: Zoo

Typically your collection will only use one type of model but models themselves are not limited to a type of collection;

  • Model: Student, Collection: Gym Class
  • Model: Student, Collection: Art Class
  • Model: Student, Collection: English Class

简单来说就是Model的聚合,没啥意思。给个例子:

[codesyntax lang="javascript"]

    var Song = Backbone.Model.extend({
    defaults: {
        name: "Not specified",
        artist: "Not specified"
    },
    initialize: function(){
        console.log("Music is the answer");
    }
});

var Album = Backbone.Collection.extend({
    model: Song
});

var song1 = new Song({ name: "How Bizarre", artist: "OMC" });
var song2 = new Song({ name: "Sexual Healing", artist: "Marvin Gaye" });
var song3 = new Song({ name: "Talk It Over In Bed", artist: "OMC" });

var myAlbum = new Album([ song1, song2, song3]);
console.log( myAlbum.models ); // [song1, song2, song3]

[/codesyntax]

Router

看看官方的说明:

Backbone routers are used for routing your applications URL's when using hash tags(#). In the traditional MVC sense they don't necessarily fit the semantics and if you have read "What is a view?" it will elaborate on this point. Though a Backbone "router" is still very useful for any application/feature that needs URL routing/history capabilities.

实质上,router对于组织项目结构、开发来说没什么意义,它只是使用了浏览器的history功能,将ajax请求友好地映射到浏览器地址栏上而已。

看个例子就明白了:

[codesyntax lang="javascript"]

    var AppRouter = Backbone.Router.extend({
    routes: {
        "posts/:id": "getPost",
        "*actions": "defaultRoute" // Backbone will try match the route above first
    }
});
// Instantiate the router
var app_router = new AppRouter;
app_router.on('route:getPost', function (id) {
    // Note the variable in the route definition being passed in here
    alert( "Get post number " + id );   
});
app_router.on('route:defaultRoute', function (actions) {
    alert( actions ); 
});
// Start Backbone history a necessary step for bookmarkable URL's
Backbone.history.start();

[/codesyntax]

Conclusion

纵观上述内容,大家不难看出,Backbone.js其实是一个很简单的框架,对于程序来说,有用的就只有Model和View这两块而已。而Model在backbone中相对比较干净点,干的都是“Model”这个概念应该干的事情。View就很苦逼了,不但要做渲染,还等于兼容了Controller的工作,这直接导致了显示渲染的代码和控制的代码耦合得非常紧密。对于大项目的制作来说,这绝对是不可接受的。

结论就是做一个小的,快速开发的项目,Backbone.js尚可,大项目的话就不要使用它了。