您的位置:首页 > Web前端 > JavaScript

Backbine.js实战第三章----事件管理

2014-10-25 21:34 183 查看
3.2基本事件方法

3.2.1 绑定on方法

使用on方法可以给一个对象的自定义事件绑定触发该事件时执行的函数,当自定义的事件触发时,绑定的函数将会被执行。其调用格式如下所示。

obj.on(eventName,function,[context]);

其中,参数Obj表示对象本身;eventName表示自定义的事件名;function表示当事件触发时,被执行的函数;可选参数context表示上下文对象,用于对象级事件的监听,即当一个对象需要监听另一个对象的事件时,可以使用该参数。

使用on方法不仅可以绑定用户的自定义事件,还可以监听对象自带的一些事件,接下来通过简单事例来进一步了解该方法的使用过程。

示例3-1 使用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:","皮卡丘");



3.源码分析

  在上述代码中,首先定义一个名为person的数据模型类。在定义时,通过defaults方法设置两个名称为“name”和“sex”的默认数据项,并将它们的值设置空。

  然后,实例化一个名为man的模型类对象,并使用on方法向该对象绑定触发change事件时执行的函数。在该函数中,将在浏览器的控制台输出“对象的默认值发生了变化”字样。即只要对象的属性值发生了变化,将触发change事件,便执行事件绑定的函数。

  最后,使用对象的set方法,重置一个name属性值,一旦修改对象的属性值,将会触发绑定的change事件。因此,当执行重置属性值代码之后,将会在浏览器的控制台输出通知文字。

示例3-2 使用on方法监听默认事件

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

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

其中,参数attrName表示对象中的属性名称;冒号(:)是过滤符,表示它是一个只针对某属性变化时触发的事件。在触发事件后的回调函数中,参数model是当前的数据模型对象,value表示名为attrName的属性修改后的值。接下来通过简单的代码来说明属性事件的触发过程。

1.功能描述

在3-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","男");




3.源码分析
在上述代码中,分别给对象man绑定了两个事件,一个是默认事件change,另一个是属性事件change:sex,即sex属性变化事件。在属性变化事件的回调函数中,通过回传的value参数获取最新修改后的属性值,并显示在浏览器的控制台中。

最后执行对象的set方法时,在Backbone内部会对已变化的值进行检测,当属性值与上次的值不同时,将会触发设置的属性事件和默认的change事件。

注意:

从上图可以看出,当修改对象的某个属性值时,其事件触发的顺序是:先触发属性事件,然后才触发默认的change事件,这一点需要注意。

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


在使用on方法绑定change和change属性事件时,还可以通过回调函数中的model对象获取属性修改前的所有值,获取方法如下代码所示。

model.previous("attrName")

model.previousAttributes()

在上述代码中,previous()方法是获取对象中某个属性的原有值,previousAttributes()方法则返回一个对象,对象中包含上一个保存状态所有属性的原有值。这两个方法只用于模型对象的change和change属性事件中获取上一个保存状态的属性值。接下来通过一个简单的示例来演示这两个方法的使用过程。

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(oldScore>value){
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(oldAge>value){
console.log("您又年轻了"+(oldAge-value)+"岁");
}else{
console.log("您的年龄没有变化");
}
});
man.set({"age":36,"score":200});




3.源码分析

    在上述代码中,通过使用on方法分别绑定对象man的change:score和change:age两个属性事件。

    在第一个属性事件change:score中,通过回调函数中model模型对象的previous()方法,获取上一次保存的score属性值,并保存至变量oldScore中;将[b]oldScore变量与最新修改的score属性值value进行比较,根据比较的结果,在浏览器的控制台中输出不同的文字。
[/b]

    在第二个属性事件change:age中,通过回调函数中model模型对象的previousAttributes()方法,获取上一次保存结果的对象,并将该对象保存至变量objAttr中;再通过访问对象变量objAttr属性的方式,获取上一次保存的age属性值,并保存至oldAge中。接下来的代码功能与change:score属性事件相同,不再赘述。

    绑定两个属性事件之后,通过调用man对象的set方法,重置了age,score两个属性值,导致了这两个事件的触发。

    从上图可以看出,默认age属性值为32,而重置时的属性值为36,它们之间相差4岁,所以在浏览器的控制台中显示“您又年长了4岁”。score属性与age属性事件过程基本一样,不再赘述。

[b]示例3-4 使用on方法绑定多个事件[/b]

1.功能描述

    在Backbone中,除了使用on方法绑定单个对象的事件,还可以使用该方法同时绑定多个对象的事件。绑定的格式有两种,第一种为各个事件使用空格隔开,格式如下。

obj.on(eventName1 eventName2,function);

    其中,使用空格隔开的参数eventName1和eventName2表示被绑定的多个事件名称,function表示所有被绑定事件都要执行的自定义函数。接下来通过一个简单的示例来说明如何获取重置时的原值与重置后的新值,并将它们输出至浏览器的控制台中。

var person = Backbone.Model.extend({
defaults:{
name:"张三",
sex:"女",
age:20,
score:30
}
});
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",200);



2.源码分析

    在上述代码中,使用on方法分别绑定了对象man的两个属性事件change:score和change:age,在绑定事件执行的函数中,首先通过模型对象的previous和get方法获取属性修改前后的值,然后通过比较这两个属性值是否发生了变化,如果发生了变化,则在浏览器的控制台中输出该属性的原值和新值。最后,通过调用man对象的set方法重置age和score属性值。

    从上图中in个,可以看出由于是按照先后顺序对man对象的属性值进行重置,因此,在控制台显示时,也是按照顺序进行显示的,如果不是按照先后顺序,而是同时对两个属性值进行重置,重置属性值代码修改如下。

man.set({"age":36,"score":200})

执行上述重置属性值时,将会在控制台输出两次一样的结果,最终在Chrome浏览器控制台输出效果如下图所示。






上图重复输出的原因在于,同时重置属性值,导致在两个属性事件分别触发的过程中,这两个属性的原值与新值都是不相同的,因此符合输出显示的条件。因为绑定两个事件,所以出现了两次重复的输出。

    在使用on方法绑定事件中,有两种格式可以绑定多个事件,除第一种使用空格之外,第二种方法为使用对象方式绑定多个事件,其调用格式如下。

var ObjEvent = {

       eventName1:function1,

       eventName2:function2

       ...

}

Obj,on(ObjEvent);

上述代码中,首先定义一个哈希对象ObjEvent,并以ket/value的方式向该对象批量添加各个事件名称和执行事件的函数,即参数eventName1和function1;然后通过使用on方法绑定该哈希对象即可。

接下来将第一种使用空格方式绑定多个事件的代码修改成使用哈希对象绑定多个事件的功能,修改代码如下所示。

var person = Backbone.Model.extend({
defaults:{
name:"张三",
sex:"女",
age:20,
score:30
}
});
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":36,score:200});
在上述代码中,首先定义一个哈希对象objEvent,在该对象中批量添加了模型对象man的两个属性事件change:score和change:age,并指定这两个属性事件执行的自定义函数分别为score_change和age_change,代码如下所示。

...

var objEvent = {

     "change:score":score_change,

     "change:age":age_change

}

...

然后,调用模型对象man的on方法绑定哈希类型对象objEvent,从而完成对象多事件的绑定。最后,调用模型对象man的set方法重置对象的age和score两个属性值,导致对应绑定属性事件的触发,其最终在Chrome浏览器中执行的结果与上图完全一致。

注意:

虽然使用上述两种方式都可以绑定对象的多个事件,但这两种方式也各具特点。在使用空格方式绑定多个事件时,需要考虑事件执行时的顺序,有重复执行的可能性,因此适合多个事件执行一个函数的场景;而使用哈希型对象的方式绑定多个事件时,每个事件所执行的函数都是一一对应的关系,代码机构非常清晰,因此适合不同事件执行不同函数的需求。



3.2.2 绑定一次once方法

在Backbone中,使用on方法可以绑定对象的事件之外,还可以使用once方法完成对象事件的绑定,只不过once方法绑定的事件只执行一次,之后即使触发也不执行。其调用的格式如下。

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

其中,参数Obj表示对象本身,eventName表示自定义的事件名,function表示当前事件触发时被执行的函数。接下来通过一个简单示例介绍它的使用方法。

[b]示例3-5 使用once方法绑定事件
[/b]

1.功能描述

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

var person = Backbone.Model.extend({
defaults:{
name:"",
sex:"女",
age:32,
score:120
}
});
var man = new person();
var intNum = 0;
man.once("change",function(){
intNum++;
console.log("事件触发的次数为"+intNum);
});
man.set("age",36);
man.set("age",37);



2.源码分析

在上述代码中,首先定义数据模型并实例化一个模型对象man,定义一个用于记录执行次数的全局变量intNum,该变量的初始值为0;然后通过man对象调用once方法,绑定对象的change事件。在该事件执行的函数中,先累加变量intNum的值,即记录该事件触发的次数,并且在控制台中输出该累加的变量intNum值。最后,两次调用man对象的set方法对age属性进行重置,

从上图看到,虽然执行了两次的属性重置操作,但绑定的change事件仅显示一次,这是由于绑定事件时,使用了once方法,而非on方法,当执行once方法绑定对象的事件后,将会自动调用内部的_once()函数,仅执行一次对象绑定的事件,因此输出的执行次数为1.针对once方法的这种特点,常常将该方法用于绑定对象的一些初始化事件中。

[b]3.2.3 触发事件trigger方法[/b]

    前面介绍了如何使用on或once方法绑定对象事件的过程,而这些事件都是对象本身自带的系统事件,如change、change:age、change:score,它们的触发都必须满足相应的条件。例如change事件,当对象中的属性值发生了变化时,才能触发,其实也能通过调用一个方法来手动触发某个事件,而这个方法就是trigger。

    trigger也是Backbone事件API中的一个重要方法,它的功能是触发对象的某一个事件,调用格式如下所示。

Obj.trigger(eventName)

    其中,参数Obj表示对象本身,eventName表示自定义的事件名,即需要手动触发的事件名称。

    使用trigger方法可以手动触发对象的任何事件,不仅是自带的系统事件,还可以是自定义的事件,接下来通过一个简单的实例介绍trigger方法的事件。


示例3-6 使用trigger方法触发事件

 1.功能描述


    先使用on方法绑定模型对象的自定义事件change_age_sex和age属性的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",37);



2.源码分析

在上述代码中,首先实例化了一个数据模型对象man,然后通过调用on方法为man对象绑定了change_age_sex自定义事件和change:age系统自带事件。在change_age_sex自定义事件中,将通过浏览器的控制台输出一段说明文字;而在系统自带的change:age事件中,将根据回调函数value的值来判断事件是否手动执行还是自动触发。如果是手动执行,在控制台中输出一段说明文字,否则输出修改后的age属性值。最后,分两次调用man对象的trigger方法手动触发自定义事件change_age_sex和系统自带事件change:age,同时使用set方法重置man对象的age属性值,导致change:age的自动触发。

从上图中看到,使用trigger方法手动触发change_age_sex事件时,在浏览器的控制台输出对应的说明文字。同样,在手动触发change:age事件时,在执行事件的代码中已通过回调函数value值检测出是否手动触发,因此只在浏览器的控制台输出对应的说明文字。然后,第三次通过set方法自动触发change:age事件时,在浏览器的控制台中则输出了修改后的age属性值37.

[b]3.2.4 移除事件off方法[/b]

在Backbone中,与绑定事件的on方法相对应的是移除事件的off方法,该方法的功能是移除对象中已绑定的某个、多个或全部的事件。其调用格式如下。

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

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

示例3-7 使用off方法移除对象的某个或多个绑定事件

在Backbone中,如果要移除对象的某个绑定事件,可以调用对象的off方法,指定需要移除的事件名称;如果有多个事件名称,则用空格隔开。

1.功能描述

先自定义两个函数,用于模型对象的on方法绑定自定义事件时调用。先使用on方法绑定自定义的事件,又调用off方法移除已绑定的事件。最后,使用trigger方法手动触发事件,观察事件触发时浏览器控制台中输出的内容。

var person = Backbone.Model.extend({
defaults:{
name:"",
sex:"女",
age:32,
score:120
}
});
var man = new person();
var m = 0;
var n = 0;
var callback_a = function(){
m++;
console.log("您执行a事件的次数为:"+m);
}
var callback_b = function(){
n++;
console.log("您执行b事件的次数为:"+n);
}
man.on("event_a",callback_a);
man.on("event_b",callback_b);
man.off("event_a");
man.trigger("event_a event_b");
man.off("event_a event_b");
man.trigger("event_a event_b");



2.源码分析

    在上述代码中,实例化一个man对象之后,首先定义两个变量m、n,分别用于记录执行不同事件的次数。其次自定义两个事件执行函数callback_a和callback_b。在这两个函数中,分别对m、n的值进行累加,并在浏览器的控制台中输出事件的名称和累加后的值。

    最后,两次使用对象的on方法分别绑定event_a和event_b事件,并首次调用对象的off方法移除绑定的event_a事件。接下来,首次调用对象的trigger方法触发event_a和event_b事件,当完成trigge方法调用后,再次使用对象的off方法移除绑定的event_a和event_b事件。此时,对象man所绑定的两个事件已经全部移除。

    从上图中看到,虽然在代码中使用on方法绑定了[b]event_a和[b]event_b两个自定义的事件,但是在第一次触发这两个事件之前,先通过off方法移除了event_a事件。因此,在第一次触发已绑定的两个事件时,实际上仅有event_b事件执行。[/b][/b]

    在第二次调用trigger方法再次触发这两个事件之前,又通过off方法移除了event_a和[b]event_b事件,因此,在第二次触发两个事件时,已经没有任何事件被执行,最终只有[b]event_b事件被执行一次。[/b][/b]



[b][b]示例3-8
使用off方法移除绑定事件的某个函数

[/b][/b]

在Backbone中,不仅可以调用对象的off方法移除已绑定的一个或多个事件,还可以移除绑定事件执行的某个函数。([b]一个事件可以绑定多个函数)[/b]

1.功能描述

在3-7的基础之上,使用off方法移除已绑定的某个函数,并观察在触发绑定事件时浏览器的控制台中输出的内容。

var person = Backbone.Model.extend({
defaults:{
name:"",
sex:"女",
age:32,
score:120
}
});
var man = new person();
var m = 0;
var n = 0;
var callback_a = function(){
m++;
console.log("您执行a事件的次数为:"+m);
}
var callback_b = function(){
n++;
console.log("您执行b事件的次数为:"+n);
}
man.on("event_a",callback_a);
man.on("event_a",callback_b);
man.trigger("event_a");
man.off("event_a",callback_b);
man.trigger("event_a");



2.源码分析

首先要明白一点,一个事件可以绑定多个function。

由于event_a最开始绑定了callback_a和callback_b,所以在触发evant_a的时候callback_a和callback_b函数都会触发。

当执行man.off("event_a",callback_b);的时候表示移除事件event_a里的指定函数callback_b,此时event_a里只有绑定了函数callback_b

所以再次执行事件event_a的时候只执行了callback_b。



[b]示例3-9 使用off方法移除对象的全部绑定事件
[/b]

在Backbone中,对象的off除了可以移除某个或多个事件、事件执行的函数外,还可以通过不带参数的方法移除全部已绑定的事件,调用格式如下所示。

Obj.off();

1.功能描述

在示例3-7的基础之上,先调用off方法移除全部已绑定的事件,然后调用trigger方法手动触发这些事件,观察浏览器控制台中内容输出的变化。

var person = Backbone.Model.extend({
defaults:{
name:"",
sex:"女",
age:32,
score:120
}
});
var man = new person();
var m = 0;
var n = 0;
var callback_a = function(){
m++;
console.log("您执行a事件的次数为:"+m);
}
var callback_b = function(){
n++;
console.log("您执行b事件的次数为:"+n);
}
man.on("event_a",callback_a);
man.on("event_a",callback_b);
man.off();
man.trigger("event_a event_b");

2.源码分析

执行修改的代码后在控制台中不会输出任何结果信息。这是因为虽然使用对象的on方法绑定event_a和event_b这两个事件,但在触发这两个绑定的事件之前,使用无参的方式调用了对象的off方法,将对象全部绑定的事件移除。因此,在执行时不会触发任何事件。所以在控制台中没有任何信息输出。





[b]3.3.1 监听事件listenTo方法
[/b]

Backbone的1.0版本中提供了监听方法,在前面章节中提高的on等事件绑定方法,其实也是监听方法的一种,只不过监听的对象不同,对象的on方法用于监听对象某事件的触发,即对象触发了这个事件,便执行相应的代码。

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

view.listenTo(model,'change',view.render);

上述监听方法也等价于如下代码。

model.on('change',view.render,view);

其中,第三个参数为上下文环境对象,此时它的值为view,即model对象在触发change事件时,关联view对象进行执行view.render动作。

通过上述对listenTo方法的简单介绍,我们知道它是一个对象级别的事件监听方法,即在执行该方法时,必须具有两个对象,其调用格式如下。

Obj1.listenTo(Obj2,EventName,function);

其中,参数Obj1、Obj2都为对象,参数EventName是Obj2对象触发的事件名称,参数function为当Obj2触发指定的EventName事件时,Obj1所执行的自定义函数。接下来通过一个简单的示例来演示listenTo方法的使用。

[b]示例3-10 使用listenTo方法监听事件
[/b]

1.功能描述

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

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");//value也是age最新值的意思
if(oldage!=newage){
console.log("age原值:"+oldage+",新值:"+newage);
}
});
man.set("age",37);



2.源码分析

在上述代码中,首先实例化了一个model对象man外,并定义了另一个事件对象obj。然后调用obj对象的listenTo方法,监听man对象的change:age事件。当触发该事件时,获取事件触发前后的age属性值,并进行比较。如果发生了 变化,则在浏览器的控制台输出原值和新值。最后调用man对象的set方法重置age属性值,用于触发change:age事件。

从上图中看到,在一个对象使用listenTo方法监听另一个对象的事件时,与对象本身调用on方法基本相同,同样可以用过回调函数获取model对象和value新值,并通过比较是否变化后输出在浏览器的控制台中。

3.3.2 监听一次listenToOnce方法

在Backbone中,除了使用listenTo方法进行对象级别事件的监听外,还可以使用listenToOnce方法进行对象级别事件的监听。这点类似于对象的on方法与once方法。对象的listenTo和listenToOnce方法最大的不同之处在于,前者是一个对象一直监听另一个对象事件的触发,而后者是仅监听一次。其调用格式如下所示。

Obj1.listenToOnce(Obj2,EventName,function);

其中,参数的说明与listenTo完全一样,不再赘述。接下来通过一个简单示例来演示调用listenToOnce方法绑定对象的属性事件。

[b]示例3-11 使用listenToOnce方法监听事件
[/b]

1.功能描述

首先使用listenToOnce方法绑定对象age属性的change事件。在该事件中,累计事件执行的次数,并将该次数的内容输出至浏览器的控制台中,然后调用set方法两次重置age属性值,触发对应的change事件,观察浏览器控制台输出内容的变化。

var person = Backbone.Model.extend({
defaults:{
name:"",
sex:"女",
age:32,
score:120
}
});
var man = new person();
var obj = _.extend({},Backbone.Events);
var intNum = 0;
obj.listenToOnce(man,"change:age",function(model,value){
intNum++;
console.log("事件触发的次数为:"+intNum);
});
man.set("age",37);
man.set("age",38);



2.源码分析

在上述代码中,首先定义两个用于监听的对象man和obj,同时定义了一个名为intNum的变量,用于记录事件触发的次数。然后,调用obj对象的listenToOnce方法监听man对象的change:age事件,当该事件触发时,intNum变量累加一次值,在浏览器的控制台中输出累加后变量intNum的值。最后,再次调用man对象的set方法,重置man对象的age属性值。

从上图中看到,虽然在代码中两次调用man对象执行set方法重置age属性值,但是,在浏览器的控制台中,事件触发的次数显示为1.这是由于obj对象使用了listenToOnce方法监听man对象的change:age事件,而listenToOnce方法的功能是只执行首次的监听操作,后续事件即使触发也不会监听,因此浏览器的控制台中显示的事件触发次数为1。

3.3.3 停止监听 stopListening方法

在Backbone中,与单个对象的off方法相同,对象级别的事件监听也有停止方法,即stopListening方法,其调用格式如下。


Obj1.stopListening(Obj2,EventName,function);

其中,参数Obj1和Obj2分别为监听发起对象和被监听对象,EventName参数为被监听对象所促发的事件名称,如果要停止监听多个事件,可以在这个参数中使用空格号隔开。另一个参数function的作用是,当触发监听事件时,监听发起对象执行的自定义函数名称。在stopListening方法中,既可以停止被监听对象的某个或多个事件的监听,也可以通过参数function在被监听对象的停止监听事件触发后,发起对象执行的自定义函数。此外,如果该方法不调用任何参数,表示停止监控全部已监控的对象事件。接下来通过一个简单的示例来演示stopListening方法的使用。



[b]示例3-12 使用stopListening方法停止监听[/b]

1.功能描述

首先使用ListenTo方法,分别绑定对象name、age、score属性的change事件,然后调用stopListening方法分别停止某个事件绑定的监听,最后调用set方法重置属性值时触发绑定的事件,观察浏览器控制台输出内容的变化。

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("name修改后的值为:"+value);
});
obj.listenTo(man,"change:age",function(model,value){
console.log("age修改后的值为:"+value);
});
obj.listenTo(man,"change:score",function(model,value){
console.log("score修改后的值为:"+value);
});
//停止监听某一个事件
obj.stopListening(man,"change:name");
man.set("name","张三");
man.set("age",35);
man.set("score",600);
//停止监听两个事件
obj.stopListening(man,"change:name change:age");
man.set("name","李四");
man.set("age",36);
man.set("score",601);
//停止监听全部事件
obj.stopListening();
man.set("name","王二");
man.set("age",37);
man.set("score",602);


2.源码分析
    在上述代码中,首先定义了两个对象man和obj,前者为被监听对象,后者为监听发起对象。然后,通过listenTo方法分别监听man对象的change:age、change:age、change:score事件,当这些事件被触发时,将在浏览器的控制台输出变化后的新值。最后,三次重置man对象的name、age、score属性值。在第一次重置前,调用对象的stopListening方法停止监听change:name事件;在第二次重置前,调用对象的stopListening方法停止监听change:name和change:age事件;在第三次重置前,调用对象的stopListening方法停止全部监听的事件。

    从上图看到,当第一次重置man对象的name、age、score属性值前,因为调用对象的stopListening方法停止监听change:name事件,在浏览器的控制台中显示了age、score修改后的值35和600;而在第二次重置man对象的三个属性值前,因为调用对象的stopListening方法停止监听change:name和change:age事件,在浏览器的控制台中显示了score修改后的值601;而在第三次重置man对象的三个属性值前,因为调用对象的stopListening方法停止全部的监听事件,没有在浏览器中输出任何信息。

[b]3.4 其他事件
[/b]

    在Backbone的事件API中,除了上述方法之外,还有一个比较特殊的事件——all,该事件无论在对象触发任何自身事件或执行自定义函数时,都会执行。此外,在整个Backbone中Events占有非常重要的地位,它以最小化模块的方式整合到Model、Collection、View类中,实现可以在这些类中自定义事件的功能,接下来详细介绍这两方面的知识。

3.4.1 特殊事件all的使用

   在Backbone中,all是一个很特殊的事件,因为该事件在对象的任何事件被触发时,它都会自动触发,可以说是一个全局性的事件。此外,既然它是一个事件,也可以通过调用对象的trigger方法进行手动触发;在触发该事件时,还可以在回调的函数中通过value参数获取当前正在触发的事件名称。其调用的格式如下。

Obj.on("all",function);

   其中,使用on方法绑定了对象的on事件,当该事件触发时,将执行自定义的回调函数function。在该函数中,可以添加一个value参数,通过该参数获取当前正在触发事件的名称。接下来通过一个简单的示例来演示all事件的运用。

示例3-13 all事件的使用

1.功能描述

    首先使用on方法绑定对象name、age属性的change事件和特殊的all事件,在这些事件中,都会向浏览器的控制台输出不同的内容。然后,调用set方法重置对象的属性值,触发对应的change事件,观察浏览器控制台输出内容的变化。

var person = Backbone.Model.extend({
defaults:{
name:"",
sex:"女",
age:32,
score:120
}
});
var man = new person();
man.on("change:age",function(model,value){
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","皮卡丘");
man.set("age",35);

2.源码分析

    在上述代码中,首先实例化一个名为man的数据模型对象,然后调用对象的on方法绑定了change:age和change:name事件,并且还绑定了all事件。在绑定all事件中,通过回调函数中的value参数获取正在触发的事件名称,并在浏览器的控制台中显示该事件名称;而在change:age和change:name事件中,分别在浏览器的控制台中显示相应触发事件的名称。最后,调用man对象的set方法分别重置对象自身的name、age属性值。

    从上图中看到,虽然只调用man方法重置了两个属性,但all事件却被触发了4次,这是由于每次重置对象属性时,不仅触发属性事件,还要触发change事件,这一点在到前面章解介绍change事件时已经介绍过。因此,当重置一个属性值时,实际上触发了两个事件,由于每个事件触发之后都会触发all事件,所以all事件被触发了4次。

    从上图中还可以看出,all事件与其他事件在触发上的顺序,都是当其他事件触发之后才触发all事件。如果在一个事件中绑定了多个执行的自定义函数,而绑定的all事件触发的顺序也将是按照函数绑定时的顺序依次触发的。

    前面也提到过,作为一个事件同样可以调用对象的trigger方法来触发,而它触发后输出什么内容呢?接下来,将代码清单3-13中最后两句对象重置的代码修改为如下。

....省略部分代码

man.trigger("all");






    从上图中看到,如果在没有任何事件触发的前提下,手动调用对象的trigger方法触发all事件,同样也会执行两次。这是由于当调用trigger方法时,会调用两次triggerEvents,一次为参数传递来的指定事件,另一次为固定的all事件。当没有任何事件名称传递过来时,其值为undefined,在Backbone框架内部的代码中,与all事件相关代码如下所示。

...

var events = this._events[name];

var allEvents = this._events.all;

if(events) triggerEvents(events,args);

if(allEvents) triggerEvents(allEvents,arguments);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: