Backbone 学习笔记 01

"Backbone 提供了一套完整的 MVC结构的 Web开发框架"

Posted by 刘一凡 on April 6, 2016

Backbone 学习笔记 01


简介

中文API

Backbone 是一个轻量级的库, 压缩后只有 16kb, 体积虽小, 但功能十分强大, 可以打造一个 模型(Model) - 视图(View) - 控制器(Controller) 即 MVC类结构的应用程序。

Model 是指数据, 比如一个人;
Collection 是指数据的集合, 比如一群人
View 是 Model 和 Collection 中数据的展示, 比如也数据渲染到页面
Router 是对路由的处理, 在单页面中通过 Router 来控制 View 的展示

依赖

Backbone.js 强制依赖 Underscore.js 这个库, 非强制依赖 jQuery, Zepto 等第三方库

<script src="jQuery.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>

第一个 Backbone 应用页面

预览效果

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>第一个 Backbone 页面应用</title>
</head>
<body>
<div id="divTip"></div>
<script src="http://apps.bdimg.com/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://apps.bdimg.com/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://apps.bdimg.com/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script>
$(function(){
  // 定义模型类
  window.Test = Backbone.Model.extend({
    defaults : {
      content : ""
    }
  })

  // 创建集合类
  window.TestList = Backbone.Collection.extend({
    model : Test
  })

  // 向模型添加数据
  var data = new TestList({
    content : "Hello, Backbone!"
  })

  // 创建 View
  window.TestView = Backbone.View.extend({
    el : $("body"),
    initialize : function(){
      $("#divTip").html(data.models[0].get("content"))
    }
  })

  // 实例化 View
  window.app = new TestView
})

</script>
</body>
</html>

依赖库 Underscore.js

Underscore.js 是一个非常简洁的, 实用的库, 包含了 60 多个独立的函数, 这些函数可以在不拓展任何原生 JavaScript 对象的情况下, 为代码开发提供丰富的实用功能.

这里就不做过多详细的介绍了, 中文API
我写过一个关于 Underscore的博客, Underscore 源码阅读

事件管理

事件管理模块 Backbone.Events 在 Backbone 中十分重要, 其他模块 Model、Collection、View 所有事件模块都依赖它。

Backbone.Events 模块 API 结构

模块 Backbone.Events 的事件管理是通过 Backbone 提供的 Events API 来实现的。
1.0版本之前仅仅提供了几个基本的方法, 如 onofftriggeronce 分别执行对事件的绑定、解除绑定、执行事件、执行一次事件。
1.0版本之后又添加了几个实用方法, 如 listenTolistenToOncestopListening 分别执行添加一个事件的侦听对象、添加一个仅执行一次的事件侦听对象和移除已添加的事件侦听对象。

基本事件方法

绑定 on 方法

使用 on 方法可以给一个对象自定义事件绑定触发该事件的执行函数, 当自定义事件触发时, 绑定的函数将运行

Obj.on(eventName, function, [context])

参数 Obj 表示对象本身; eventName 表示自定义事件名; function 表示当事件触发时, 被执行的函数; 可选参数 context 表示上下文环境

示例一 : 使用 on 方法监听默认事件

1.功能描述

构建一个名为 person 的模型类, 通过 defaults 设置对象的默认属性, 使用 on 方法 绑定对象默认属性的 change 事件

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : ""
    }
});

var man = new person();
man.on("change", function(){
    console.log("对象的属性值发生了改变")
})
man.set("name", "Lyf");

=> 输出 对象的属性值发生了改变

示例二 : 使用 on 方法监听属性事件

使用 on 方法监听对象的 change 事件时, 还可以监听到某个属性值的变化事件, 即属性事件。

Obj.on(eventName:attrName, function(model, value))

参数 eventName:attrName 表示对象的属性名称; 冒号(:) 是过滤符, 表示它是一个只针对某属性变化时触发的事件;
在触发的回调中, 参数 model, 表示当前的数据模型对象, value 表示名为 attrName 属性修改后的值

1.功能描述

在示例一的基础上, 使用 on 方法绑定对象中是 sex 属性的 change 事件, 当 sex 属性值发生改变时, 触发该事件, 并在控制台输出最新值.

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "女"
    }
});

var man = new person();
man.on("change", function(){
    console.log("对象的属性值发生了改变")
})
man.on("change:sex", function(model, value){
  console.log("您修改了性别属性值, 最新值是 : " + value)
})
man.set("sex", "男")

=> 您修改了性别属性值, 最新值是 : 男
=> 对象的属性值发生了改变

注意 : 当修改对象属性值的时候, 其事件的触发顺序是 : 先触发属性事件, 然后才触发默认的 change 事件

示例三 : 使用 on 方法获取属性修改前的值

使用 on 方法监听对象的 change 事件和 change 属性事件时, 还可以通过回调函数中的 model 对象获取属性修改前的值 :

model.previous("attrName")
model.previousAttributes()

previous() 方法是获取对象中某个属性的原有值, previousAttribute() 方法返回一个对象, 对象中包含上一个保存状态中的所有属性的原有值。这个方法只用于模型对象的 changechange 属性事件中获取上一个保存状态的属性值。

1.功能描述

分别绑定”分数”、”年龄”、属性的 change 事件。在事件中, 分别将属性重置前后的值进行对比, 并根据对比值在不同的浏览器的控制台中输出不同的内容.

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "女",
        age : 32,
        score : 120
    }
});

var man = new person();
man.on("change:score", function(model, value){
    var oldscore = model.previous("score")
    if(value > oldscore){
      console.log("您比上次进步了" + (value - oldscore) + "分")
    } else if(value < oldscore){
      console.log("您比上次落后了" + (oldscore - value) + "分")
    } else {
      console.log("您的成绩没有变化")
    }
})
man.on("change:age", function(model, value){
  var objAttr = model.previousAttributes();
  var oldAge = objAttr.age;
  if(value > oldAge){
    console.log("您又年长了" + (value - oldAge) + "岁")
  } else if(value < oldAge) {
    console.log("您又年轻了" + (oldAge - value) + "岁")
  } else {
    console.log("您的年龄没有变化")
  }
})
man.set({"age" : 35, "score" : 150})

=> 您又年长了3岁
=> 您比上次进步了30分

示例四 : 使用 on 方法绑定多个事件

在 Backbone 中, 除了使用 on 绑定单个事件, 还可以使用该方法同时绑定多个对象的事件.
绑定的方法有两种, 第一种语法如下 :

Obj.on(eventName1 eventName2, function)

使用空格隔开的参数 eventName1eventName2 表示被绑定的多个事件的名称, function 表示所有被绑定的事件都要执行的自定义函数

1.功能描述

使用模型对象的 on 方法, 同时绑定 score、age 属性的 change 事件, 在该事件中, 分别获取重置时的原值和重置后的新值

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "女",
        age : 32,
        score : 120
    }
});

var man = new person();
man.on("change:score change:age", function(model, value){
  var oldage = model.previous("age");
  var newage = model.get("age");
  if(oldage != newage){
    console.log("age 原值为 : " + oldage + ", 新值 : " + newage)
  }
  var oldscore = model.previous("score");
  var newscore = model.get("score");
  if(oldscore != newscore){
    console.log("score 原值为 : " + oldscore + ", 新值 : " + newscore)
  }
});

man.set("age", 36);
man.set("score", 150);

=> age 原值为 : 32, 新值 : 36
=> score 原值为 : 120, 新值 : 150

在使用 on 方法绑定事件中, 有两种格式可以绑定多个事件, 除了第一种使用空格外, 第二种方式为使用对象方式绑定多个事件 :

var ObjEvent = {
    eventName1 : function1,
    eventName2 : function2,
    ...
}

Obj.on(ObjEvent)

实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "女",
        age : 32,
        score : 120
    }
});

var man = new person();
var objEvent = {
    "change:score" : score_change,
    "change:age" : age_change
}
man.on(objEvent);

function score_change(model, value){
    var oldscore = model.previous("score");
    var newscore = model.get("score");
    if(oldscore != newscore){
      console.log("score 原值为 : " + oldscore + ", 新值 : " + newscore)
    }
}

function age_change(model, value){
    var oldage = model.previous("age");
    var newage = model.get("age");
    if(oldage != newage){
      console.log("age 原值为 : " + oldage + ", 新值 : " + newage)
    }
}

man.set({"age" : 35, "score" : 150})

=> age 原值为 : 32, 新值 : 35
=> score 原值为 : 120, 新值 : 150

绑定一次 once 方法

once 方法绑定的事件只执行一次, 之后即使触发也不执行。调用格式如下 :

Obj.once(eventName, function, [context])

示例五 : 使用 once 方法绑定事件

1.功能描述

先使用模型对象的 once 方法绑定 change 事件, 在该事件中通过变量累计事件执行的次数, 并将该次数内容输出至浏览器的控制台中, 然后用 set 方法重置二次模型对象的属性.

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var initNum = 0;
man.once("change", function(){
  initNum++;
  console.log("事件触发的次数为" + initNum)
});
man.set("age", 26);
man.set("score", 150);

=> 事件触发的次数为1

触发事件 trigger 方法

前面介绍了 on 或者 once 方法绑定对象事件的过程, 这些事件都是对象本身自带的系统事件, 如 changechange:age 等, 他们的触发需要满足相应的条件.
trigger 的功能是触发对象的某个事件 :

Obj.trigger(eventName)

其中 Obj 为对象本身, eventName 表示自定义的事件名, 需要手动触发的事件名。
trigger 可以手动触发对象的任何事件, 不仅是系统自带的事件, 还可以是自定义的事件。

示例六 : 使用 trigger 方法触发事件

1.功能描述

先使用 on 方法绑定模型对象的自定义事件 change_age_sexage 属性的 change 事件, 然后分别调用 trigger 方法手动触发绑定的事件.

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
man.on("change_age_sex", function(){
  console.log("您手动触发了一个自定义事件")
})
man.on("change:age", function(model, value){
  if(value !== undefined)
    console.log("您修改后的年龄为" + value)
  else
    console.log("您手动触发了一个年龄修改事件")
})
man.trigger("change_age_sex");
man.trigger("change:age");
man.set("age", 26);

=> 您手动触发了一个自定义事件
=> 您手动触发了一个年龄修改事件
=> 您修改后的年龄为26

移除事件 off 事件

与绑定事件的 on 方法相对的是移除事件的 off 方法, 该方法的功能是移除对象已绑定的某个、多个或全部的事件

Obj.off(eventName, function, [context]) 

其中参数 eventName 表示被移除的绑定事件名称, 该名称可以是单个也可以是多个, 如果是多个事件, 则用空格隔开。除移除对象绑定的事件之外, 还可以移除事件执行的函数, 即通过参数 function 来表示被移除的事件函数名。如果在调用 off 方法时不带任何参数, 表示移除对象的全部绑定事件。

示例七 : 使用 off 方法移除对象的某个或者多个事件

1.功能描述

先使用 on 方法绑定自定义事件, 又调用 off 方法移除已绑定的事件。

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var m = 0, n = 0;
var call_back_a = function(){
  m++;
  console.log("您执行a事件的次数为" + m);
}
var call_back_b = function(){
  n++;
  console.log("您执行b事件的次数为" + n);
}
man.on("event_a", call_back_a);
man.on("event_b", call_back_b);
man.off("event_a");
man.trigger("event_a event_b");
man.off("event_a event_b");
man.trigger("event_a event_b");

=> 您执行b事件的次数为1

示例八 : 使用 off 方法移除对象的某个函数

1.功能描述

使用 off 方法移除对象的某个函数

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var m = 0, n = 0;
var call_back_a = function(){
  m++;
  console.log("您执行a事件的次数为" + m);
}
var call_back_b = function(){
  n++;
  console.log("您执行b事件的次数为" + n);
}
man.on("event_a", call_back_a);
man.on("event_b", call_back_b);
man.off("event_a", call_back_a);
man.trigger("event_a event_b");
man.off("event_b", call_back_b);
man.trigger("event_a event_b");

=> 您执行b事件的次数为1

示例九 : 使用 off 方法移除对象全部绑定事件

在 Backbone 中, off 方法还可以通过不带参数的方式移除全部已绑定的事件。

1.功能描述

使用 off 移除全部已绑定的事件

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var m = 0, n = 0;
var call_back_a = function(){
  m++;
  console.log("您执行a事件的次数为" + m);
}
var call_back_b = function(){
  n++;
  console.log("您执行b事件的次数为" + n);
}
man.on("event_a", call_back_a);
man.on("event_b", call_back_b);
man.off();
man.trigger("event_a event_b");

新增事件方法

监听事件 listenTo 方法

相对于 on 方法而言, listenTo 方法的监听效果更为突出, 它是一个对象监听另一个对象的事件, 如果被监听的对象触发了被监听的事件, 执行相应的回调函数或代码块。
例如: view 对象要监听 model 对象的 change 事件, 如果 mode 对象触发了 change 事件, 则需要刷新当前 view 对象, 即执行下面代码 :

view.listenTo(model, "change", view.render)

也等价于

model.on("change", view.render, view)

其调用格式为

Obj1.listenTo(Obj2, eventName, function)

其中 Obj1Obj2 都是对象, eventNameObj2 对象的触发事件名称, function 为当 Obj2 触发事件时调用的函数。

示例十 : 使用 listenTo 方法监听事件

1.功能描述

先调用 listenTo 方法绑定模型对象 age 属性的 change 事件。然后调用 set 方法重置对象的 age 属性, 在浏览器中输出变化时的原值与新值。

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var obj = _.extend({}, Backbone.Events);
obj.listenTo(man, "change:age", function(model, value){
  var oldage = model.previous("age");
  var newage = model.get("age");
  if(oldage != newage){
    console.log("age 原值" + oldage + ", 新值 : " + newage)
  }
});
man.set("age", 37);

=> age 原值32, 新值 : 37

监听一次 listenToOnce 方法

除了使用 listenTo 方法可以进行对象级别监听外, 还可以使用 listenToOnce 方法进行对象级别的事件监听。

Obj1.listenToOnce(Obj2, EventName, function)

示例十一 : 使用 listenToOnce 方法监听事件

1.功能描述

先使用 listenToOnce 方法绑定对象 age 属性的 change 事件, 在事件中累计事件执行的次数, 并将次数输出。

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var obj = _.extend({}, Backbone.Events);
var initNum = 0;
obj.listenToOnce(man, "change:age", function(){
  initNum++;
  console.log("事件触发的次数为:" + initNum);
});
man.set("age", 37);
man.set("age", 38);

=> 事件触发的次数为:1

停止监听 stopListening 方法

与单个对象的 off 方法相同, 对象级别的事件监听也有停止方法即 stopListening 方法 :

Obj1.stopListening(Obj2, eventName, function)

示例十二 : 使用 stopListening 方法停止监听事件

1.功能描述

先使用 listenTo 方法绑定对象 age 属性的 change 事件, 然后分别调用 stopListening 方法停止事件的监听。

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
var obj = _.extend({}, Backbone.Events);
obj.listenTo(man, "change:name", function(model, value){
  console.log("姓名修改后的值为:" + value);
});
obj.listenTo(man, "change:age", function(model, value){
  console.log("年龄修改后的值为:" + value);
});
obj.listenTo(man, "change:score", function(model, value){
  console.log("分数修改后的值为:" + value);
});
// 停止监听某一事件
obj.stopListening(man, "change:name");
man.set("name", "张三");
man.set("age", 25);
man.set("score", 150);
// 停止监听两个事件
obj.stopListening(man, "change:name change:age");
man.set("name", "李四");
man.set("age", 35);
man.set("score", 250);
// 停止所有事件
obj.stopListening();
man.set("name", "赵六");
man.set("age", 45);
man.set("score", 350);

=> 年龄修改后的值为:25
=> 分数修改后的值为:150
=> 分数修改后的值为:250

事件其他

特殊事件 all 的使用

all 是一个特殊的事件, 因为该事件在对象的任何事件被触发时, 它都会触发, 可以说是一个全局事件。它可以用 trigger 触发; 在触发该事件时, 还可以在回调的函数中通过 value 参数获取当前正在触发的事件名称。

Obj.on("all", function)

示例十三 : all 事件使用

1.功能描述

首先使用 on 方法绑定对象 nameage 属性的 change 事件和特殊事件 all, 然后在浏览器中输出

2.实现代码

var person = Backbone.Model.extend({
    defaults : {
        name : "",
        sex : "男",
        age : 32,
        score : 120
    }
});

var man = new person();
man.on("change:age", function(){
  console.log("您触发了change:age事件");
});
var event_fun = function(){
  console.log("您触发了change:name事件");
}
man.on("change:name", event_fun);
man.on("all", function(value){
  console.log("您触发了all事件中" + value);
});
man.set("name", "Lyf");
man.set("age", 20);

=> 您触发了change:name事件
=> 您触发了all事件中change:name
=> 您触发了all事件中change
=> 您触发了change:age事件
=> 您触发了all事件中change:age
=> 您触发了all事件中change

事件与 Model、Collection 、View 的关系

示例十四 : 在 View 模块中定义事件

1.功能描述

在构建视图类时, 定义页面中的两个按钮的单击事件。单击”显示”按钮, 将页面中展示 <div> 元素的内容, 单击”隐藏”按钮时, 将隐藏 <div> 元素中的内容。

2.实现代码

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>View 模块中的事件</title>
    <style type="text/css">
    body{
      font-size: 12px;
    }
    </style>
</head>
<body>
<div id="view">
  <input type="button" value="显示" id="btnShow">
  <input type="button" value="隐藏" id="btnHide">
</div>
<div id="Info">
  <span>This is a text .</span>
</div>
<script src="http://apps.bdimg.com/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://apps.bdimg.com/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://apps.bdimg.com/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script>
var infoView = Backbone.View.extend({
  el : "#view",
  events : {
    "click #btnShow" : "ShowInfo",
    "click #btnHide" : "HideInfo"
  },
  ShowInfo : function(){
    $("#Info").show();
  },
  HideInfo : function(){
    $("#Info").hide()
  }
});

var view = new infoView();
</script>
</body>
</html>

演示代码