• [backbone] Getting Started with Backbone.js


    一、简介

    Backbone 是一个 JavaScript MVC 框架,它属于轻量级框架,且易于学习掌握。
    模型、视图、集合和路由器从不同的层面划分了应用程序,并负责处理几种特定事件。
    处理 Ajax 应用程序或者 SPI 应用程序时,Backbone 可能是最好的解决方案。

    二、详细介绍

    Backbone的四大核心组件:

    • Model
    • Collection
    • View
    • Controller

    Modal

    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.

    模型是任何JavaScript应用程序的核心,包含交互式数据以及围绕它的逻辑的很大一部分:转换、验证、计算性能和访问控制。要创建一个模型,需要扩展 Backbone.Model。

      例子:

    最简定义:var Game = Backbone.Model.extend({});
    
    拓展:
    
        var Game = Backbone.Model.extend({
            initialize: function(){
                alert("Oh hey! Backbone!");
            },
              defaults: {
           // default attribute name:
    'Default title', releaseDate: 2011, } }); #initialize will be fired when an object is instantiated. #initialize 部分当Game对象实例化的时候将会被触发 #创建实例化对象
    #必须创建一个实例才能在应用程序中使用特定模型
    var portal = new Game({ name: "Portal 2", releaseDate: 2011}); #获取属性值 var release = portal.get('releaseDate'); #设置属性值 portal.set({ name: "Portal 2 by Valve"}); #当调用set方法后,仅仅只是改变了内存中的值,如果想要在服务器中持久化值,需要调用save()方法。发送的是POST请求。 portal.save();

    Collection

    Collections in Backbone are essentially just a collection of models. Going with our database analogy from earlier, collections are the results of a query where the results consists of a number of records [models].

    Backbone中,collection的基本含义就是“许多modal的集合”。如果与我们早期的数据库类比,collection就好比是一个查询的结果集,这个结果集由一系列的记录[modal]组成。

      例子:

      

    最简定义:表示这个集合的基本modal类型是Game
    
    var GamesCollection = Backbone.Collection.extend({
      model : Game,
    }); 拓展定义:通过新增的方法返回特定的集合数据 add a method that returns only specific games.
    var GamesCollection = Backbone.Collection.extend({ model : Game, old : function() { return this.filter(function(game) { return game.get('releaseDate') < 2009; }); } }); 也可以直接操作一个集合的内容 var games = new GamesCollection(); games.get(0);//或者 games.at(0);
    使用 add()/remove() 方法可以将一个模型添加和移动到集合中。

      App.Collections.Teams = Backbone.Collection.extend({
        model : App.Models.Team
      });

      var teams = new App.Collections.Teams();
      teams.add(team1);
      teams.add(new App.Models.Team({name : "Team B"}));
      teams.add(new App.Models.Team());
      teams.remove(team1);

      console.log(teams.length) // prints 2
      console.log(teams.fetch());//取得集合包含的模型阵列

    最后,可以动态地填充集合
    var GamesCollection = Backbone.Collection.extend({
      model : Game,
      url: '/games'
    });
     
    var games = new GamesCollection();
    games.fetch();
    这也是常用的获取集合数据的方法

    View

    Backbone 视图可以扩展 Backbone.View 函数并显示模型中存储的数据。
    视图的主要目的:渲染数据

    ————————————————————————————————————

    (1)定义视图基准tag

    一个视图提供一个由 el 属性定义的 HTML 元素。
    该属性可以是由 tagName、className 和 id 属性相组合而构成的,或者是通过其本身的 el 值形成的。
    如果 el、tagName、className 和 id 属性为空,那么会默认将一个空的 DIV 分配给 el。

    例如:

    // In the following view, el value is 'UL.team-element'
    App.Views.Teams = Backbone.View.extend({
        el : 'UL.team-list'
    });
    
    // In the following view, el value is 'div.team-element'
    App.Views.Team = Backbone.View.extend({
        className : '.team-element',
        tagName : 'div'
    });
    
    // In the following view, el value is 'div'
    App.Views.Team = Backbone.View.extend({
    });

    (2)视图模型关联

    一个视图必须与一个模型相关联。
    App.View.Team 视图被绑定到一个 App.Models.Team 模型实例。

    App.Views.Team = Backbone.View.extend({
      el : 'UL.team-list',
      ...
      model : new App.Models.Team
    });

    (3)渲染数据

    重写 render() 方法和逻辑来显示 DOM 元素(由 el 属性引用的)中的模型属性。

    #更新用户界面样例
    App.Views.Team = Backbone.View.extend({
        className : '.team-element',
        tagName : 'div',
        model : new App.Models.Team
        render : function() {
            // Render the 'name' attribute of the model associated
            // inside the DOM element referred by 'el'
            $(this.el).html("<span>" + this.model.get("name") + "</span>");
        }
    });

    (4)客户端模板

    使用 Backbone 客户端模板 可以避免在 JavaScript 中嵌入 HTML 代码。
    使用模板,模板会封装视图中常见函数;只指定此函数一次即可。
    Backbone 在 underscore.js(一个必须的库)中提供一个模板引擎。

    #使用 underscore.js HTML 模板
    <script id="teamTemplate" type="text/template">
        <%= name %>
    </script>
    
    
    #使用 _.template() 函数的视图
    App.Views.Team = Backbone.View.extend({
        className : '.team-element',
        tagName : 'div',
        model : new App.Models.Team
        render : function() {
            // Compile the template
            var compiledTemplate = _.template($('#teamTemplate').html());
            // Model attributes loaded into the template. Template is
            // appended to the DOM element referred by the el attribute
            $(this.el).html(compiledTemplate(this.model.toJSON()));
        }
    });
    
    #将 render() 方法绑定到模型变更事件 bind("change",function(){})
    #当模型发生更改时,会自动触发 render() 方法,从而节省数行代码。
    App.Views.Team = Backbone.View.extend({
        model : new App.Models.Team,
        initialize : function() {
            this.model.bind("change", this.render, this);
        } 
    })

    (5)综合例子

    #定义视图
    var GameView= Backbone.View.extend({
        tagName : "div",
        className: "game",
        render : function() {
            
            //dom way
            //这里的this.el 相当于是  class = game的那个div节点
            this.el.innerHTML = this.model.get('name');
           
             //jQuery way
            $(this.el).html(this.model.get('name'));
        }
    });
    
    #通过dom节点监听事件
    events: {
        'click .name': 'handleClick'
    },      
    handleClick: function(){
        alert('In the name of science... you monster');
    }
        

    Controller

    类似于SpringMVC 中根据不同的URI和参数来路由到不同的方法进行处理

    #基础定义
    var Hashbangs = Backbone.Controller.extend({
      routes: {
        "/":                 "root",
        "/games":        "games",
      },
      root: function() {
        // Prep the home page and render stuff
      },
      games: function() {
        // Re-render views to show a collection of books
      },
    });

    #或者

    var App.Routers.Main = Backbone.Router.extend({

      // Hash maps for routes
      routes : {
        "" : "index",
        "/teams" : "getTeams",
        "/teams/:country" : "getTeamsCountry",
        "/teams/:country/:name : "getTeam"
        "*error" : "fourOfour"
      },

      index: function(){
        // Homepage
      },

      getTeams: function() {
        // List all teams
      },
      getTeamsCountry: function(country) {
        // Get list of teams for specific country
      },
      getTeam: function(country, name) {
        // Get the teams for a specific country and with a specific name
      },
      fourOfour: function(error) {
        // 404 page
      }
    });

    
    

    http://www.example.com -> 触发 index()
    http://www.example.com/#/teams -> 触发 getTeams()
    http://www.example.com/#/teams/country1 -> 触发 getTeamsCountry() 传递 country1 作为参数
    http://www.example.com/#/teams/country1/team1 -> 触发 getTeamCountry() 传递 country1 和 team1 作为参数
    http://www.example.com/#/something 触发 fourOfour() -> 以作 * (星号)使用。

    注意:

    当实例化路由器(控制器)时,会生成 Backbone.history 对象(控制浏览器前进或后退的对象);
    它将自动引用 Backbone.History 函数。
    Backbone.History 负责匹配路由和 router 对象中定义的活动。
    start() 方法触发后,将创建 Backbone.history 的 fragment 属性。它包含散列片段的值。该序列在根据状态次序管理浏览器历史方面十分有用。用户如果想要返回前一状态,单击浏览器的返回按钮。

    #因此,为避免扰乱后退按钮,请执行如下的代码:
    var ApplicationController = new Controller(); 
    Backbone.history.start();

      var router = new App.Routers.Main();
      Backbone.history.start({pushState : true});

    不得不说的重要属性和方法

    (1)url
    定义了使用 Ajax GET 请求从服务器取出 JSON 数据的位置
    teams.url = '/getTeams';
    teams.fetch(); //Ajax GET Request to '/getTeams'
    2)存取 save() / fetch()
    
    Backbone 的一个重要特性是易于通过 Ajax 交互与服务器进行通信。
    在模型上调用一个 save() 方法会通过 REST JSON API 异步将当前状态保存到服务器。
    
    barca.save();
    
    save()函数将在后台委托给 Backbone.sync,这是负责发出 RESTful 请求的组件,默认使用 jQuery 函数 $.ajax()。
    由于调用了 REST 风格架构,每个 Create、Read、Update 或 Delete (CRUD) 活动均会与各种不同类型的 HTTP 请求(POST、GET、PUT 和 DELETE)相关联。
    首先保存模型对象,使用一个 POST 请求,创建一个标识符 ID,其后,尝试发送对象到服务器,使用一个 PUT 请求。
    
    当需要从服务器检索一个模型时,请求一个 Read 活动并使用一个 Ajax GET 请求。这类请求使用 fetch() 方法。
    Fetch() 方法属于异步调用,因此,在等待服务器响应时,应用程序不会中止。
    
    要确定导入模型数据或者从中取出模型数据的服务器的位置:
    
    A.如果模型属于一个 collection,那么集合对象的 url 属性将是该位置的基础,并且该模型 ID(不是 cid)会被附加以构成完整的 URL。
    
    B.如果模型不是在一个集合中,那么该模型的 urlroot 属性被用作该位置的基础
    
    
    如:
    var teamNew = new App.Models.Team({
        urlRoot : '/specialTeams'
    });
    teamNew.save(); // returns model's ID equal to '222'
    teamNew.fetch(); // Ajax request to '/specialTeams/222'
    3)parse()
    要操作来自服务器的原始数据,可以使用集合的 parse() 方法。
    App.Collections.Teams = Backbone.Collection.extend({
        model : App.Models.Team,
        parse : function(data) {
            // 'data' contains the raw JSON object
            console.log(data);
        }
    });
    
    (4)验证 validate() 
    
    需要重写 validate() 方法(在调用 set() 方法时触发)来包含模型的有效逻辑。
    传递给该函数的惟一参数是一个 JavaScript 对象,该对象包含了 set()方法更新的属性,以便验证那些属性的条件。
    如果从 validate() 方法中没有返回任何内容,那么验证成功。如果返回一个错误消息,那么验证失败,将无法执行 set() 方法。
    
    
    App.Models.Team = Backbone.Model.extend({
        validate : function(attributes){
            if (!!attributes && attributes.name === "teamX") {
                // Error message returned if the value of the "name" 
                // attribute is equal to "teamX"
                return "Error!";
            }
        }
    }
    
    
    (5)获取HTML模版代码
    
    HTML代码
    <script id="teamTemplate" type="text/template">
        <%= name %>
    </script>
    
    获取方法
    _.template($('#teamTemplate').html())
    
    
    (6)绑定模型事件
    
    在 Backbone 0.5.2 之前的版本中,必须使用 underscore.js 中的 _.bindAll() 函数
    
    0.5.2 之前的版本
    App.Views.Team = Backbone.View.extend({
        initialize : function() {
            _.bindAll(this, "render");
            //注意这里的bind只有两个参数
            this.model.bind("change", this.render);
        } 
    })
    
    0.5.2之后的版本
    App.Views.Team = Backbone.View.extend({
        model : new App.Models.Team,
        initialize : function() {
            //注意这里的bind有三个参数
            this.model.bind("change", this.render, this);
        } 
    })

    拓展阅读:

    1、backbone.js手册

    http://documentcloud.github.io/backbone/?cm_mc_uid=04584153933614497181707&cm_mc_sid_50200000=1450061719

    http://www.css88.com/doc/backbone/(中文API)

    Events
    – on
    – off
    – trigger
    – once
    – listenTo
    – stopListening
    – listenToOnce
    - Catalog of Built-in Events
    
    Modal
    – extend
    – constructor / initialize
    – get
    – set
    – escape
    – has
    – unset
    – clear
    – id
    – idAttribute
    – cid
    – attributes
    – changed
    – defaults
    – toJSON
    – sync
    – fetch
    – save
    – destroy
    – Underscore Methods (6)
    – validate
    – validationError
    – isValid
    – url
    – urlRoot
    – parse
    – clone
    – isNew
    – hasChanged
    – changedAttributes
    – previous
    – previousAttributes
    
    
    Collection
    – extend
    – model
    – constructor / initialize
    – models
    – toJSON
    – sync
    – Underscore Methods (28)
    – add
    – remove
    – reset
    – set
    – get
    – at
    – push
    – pop
    – unshift
    – shift
    – slice
    – length
    – comparator
    – sort
    – pluck
    – where
    – findWhere
    – url
    – parse
    – clone
    – fetch
    – create
    
    
    Router
    – extend
    – routes
    – constructor / initialize
    – route
    – navigate
    
    History
    – start
    
    Sync
    – Backbone.sync
    – Backbone.ajax
    – Backbone.emulateHTTP
    – Backbone.emulateJSON
    
    
    View
    – extend
    – constructor / initialize
    – el
    – $el
    – setElement
    – attributes
    – $ (jQuery)
    – render
    – remove
    – delegateEvents
    – undelegateEvents
    
    
    Utility
    – Backbone.noConflict
    – Backbone.$

    2、underscore.js手册

    http://documentcloud.github.io/underscore/

    http://www.css88.com/doc/underscore/(中文API)

    针对如下的类型封装了很多操作的方法
    调用方法时,在方法前加上  " _.  "
    比如:

    Collection中 each 为 _.each(list, iterator, [context])
    _.each([1, 2, 3], alert);
    => alerts each number in turn...
    _.each({one : 1, two : 2, three : 3}, alert); => alerts each number value in turn...
    map 为 _.map(list, iterator, [context])
    _.map([1, 2, 3], function(num){ return num * 3; });
    => [3, 6, 9]
    _.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; }); => [3, 6, 9]


    find_.find(list, iterator, [context]) 
    var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    => 2

    filter 为 _.filter(list, iterator, [context])
    var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    => [2, 4, 6]

    Functions中
    bind_.bind(function, object, [*arguments]) 
    var func = function(greeting){ return greeting + ': ' + this.name };
    func = _.bind(func, {name : 'moe'}, 'hi');
    func();
    => 'hi: moe'
    bindAll_.bindAll(object, *methodNames) 
    var buttonView = {
      label   : 'underscore',
      onClick : function(){ alert('clicked: ' + this.label); },
      onHover : function(){ console.log('hovering: ' + this.label); }
    };
    _.bindAll(buttonView, 'onClick', 'onHover');
    // When the button is clicked, this.label will have the correct value.
    jQuery('#underscore_button').bind('click', buttonView.onClick);
    delay_.delay(function, wait, [*arguments]) 
    var log = _.bind(console.log, console);
    _.delay(log, 1000, 'logged later');
    => 'logged later' // Appears after one second.
    
    #以下是比较全面的方法
    collections
    - each
    - map
    - reduce
    - reduceRight
    - find
    - filter
    - where
    - findWhere
    - reject
    - every
    - some
    - contains
    - invoke
    - pluck
    - max
    - min
    - sortBy
    - groupBy
    - countBy
    - shuffle
    - toArray
    - size
    
    arrays
    - first
    - initial
    - last
    - rest
    - compact
    - flatten
    - without
    - union
    - intersection
    - difference
    - uniq
    - zip
    - unzip
    - object
    - indexOf
    - lastIndexOf
    - sortedIndex
    - range
    
    functions
    - bind
    - bindAll
    - partial
    - memoize
    - delay
    - defer
    - throttle
    - debounce
    - once
    - after
    - wrap
    - compose
    
    objects
    - keys
    - values
    - pairs
    - invert
    - functions
    - extend
    - pick
    - omit
    - defaults
    - clone
    - tap
    - has
    - isEqual
    - isEmpty
    - isElement
    - isArray
    - isObject
    - isArguments
    - isFunction
    - isString
    - isNumber
    - isFinite
    - isBoolean
    - isDate
    - isRegExp
    - isNaN
    - isNull
    - isUndefined
    
    
    utility
    - noConflict
    - identity
    - times
    - random
    - mixin
    - uniqueId
    - escape
    - unescape
    - result
    - template
    
    chaining
    - chain
    - value

    3、backbone的5个小例子

    http://arturadib.com/hello-backbonejs/docs/1.html

  • 相关阅读:
    求1+2+3+...+n
    孩子们的游戏(圆圈中最后剩下的数) 约瑟夫环
    扑克牌顺子
    翻转单词顺序列
    左旋转字符串
    和为S的两个数字
    和为S的连续正数序列
    CocoaPods 更新
    UITextView 动态高度计算(iOS7版)
    Mac 把图片反色
  • 原文地址:https://www.cnblogs.com/avivaye/p/5044601.html
Copyright © 2020-2023  润新知