发布在:事件

介绍自定义事件

link 自定义事件

我们都熟悉基本事件(单击、鼠标悬停、焦点、模糊、提交等),当用户与浏览器交互时,我们可以利用这些事件。自定义事件开辟了一个全新的事件驱动编程世界。

一开始可能很难理解为什么你想使用自定义事件,因为内置事件似乎完全满足你的需求。事实证明,自定义事件提供了一种全新的事件驱动 JavaScript 思维方式。自定义事件不是关注触发操作的元素,而是关注被操作的元素。这带来了很多好处,包括

  • 使用相同的代码,不同元素可以轻松触发目标元素的行为。
  • 可以在多个类似的目标元素上同时触发行为。
  • 行为在代码中与目标元素关联得更清晰,使代码更易于阅读和维护。

你为什么要关心?一个例子可能是解释的最佳方式。假设你家一间屋子里有一个灯泡。灯泡当前已打开,由两个三通开关和一个拍手器控制

1
2
3
4
5
6
<div class="room" id="kitchen">
<div class="lightbulb on">Kitchen light</div>
<div class="switch">Kitchen switch 1</div>
<div class="switch">Kitchen switch 2</div>
<div class="clapper">Kitchen clapper switch</div>
</div>

触发拍手器或任何一个开关都会改变灯泡的状态。开关和拍手器不在乎灯泡处于什么状态;他们只想改变状态。

如果没有自定义事件,你可能会编写这样的代码

1
2
3
4
5
6
7
8
$( ".switch, .clapper" ).click(function() {
var light = $( this ).closest( ".room" ).find( ".lightbulb" );
if ( light.is( ".on" ) ) {
light.removeClass( "on" ).addClass( "off" );
} else {
light.removeClass( "off" ).addClass( "on" );
}
});

使用自定义事件,您的代码可能更像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
$( ".lightbulb" ).on( "light:toggle", function( event ) {
var light = $( this );
if ( light.is( ".on" ) ) {
light.removeClass( "on" ).addClass( "off" );
} else {
light.removeClass( "off" ).addClass( "on" );
}
});
$( ".switch, .clapper" ).click(function() {
var room = $( this ).closest( ".room" );
room.find( ".lightbulb" ).trigger( "light:toggle" );
});

这段代码的最后部分并不令人兴奋,但发生了一件重要的事情:我们将灯泡的行为从开关和拍手器移到了灯泡本身。

让我们让我们的示例更有趣一些。我们将为我们的房子添加另一个房间,以及一个主开关,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="room" id="kitchen">
<div class="lightbulb on">Kitchen light</div>
<div class="switch">Kitchen switch 1</div>
<div class="switch">Kitchen switch 2</div>
<div class="clapper">Kitchen clapper switch</div>
</div>
<div class="room" id="bedroom">
<div class="lightbulb on">Bedroom light</div>
<div class="switch">Bedroom switch 1</div>
<div class="switch">Bedroom switch 2</div>
<div class="clapper">Bedroom clapper switch</div>
</div>
<div id="master_switch">Master switch</div>

如果房子里有任何灯亮着,我们希望主开关关闭所有灯;否则,我们希望它打开所有灯。为了实现这一点,我们将向灯泡添加另外两个自定义事件:light:onlight:off。我们将在 light:toggle 自定义事件中使用它们,并使用一些逻辑来决定主开关应该触发哪一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$( ".lightbulb" ).on( "light:toggle", function( event ) {
var light = $( this );
if ( light.is( ".on" ) ) {
light.trigger( "light:off" );
} else {
light.trigger( "light:on" );
}
}).on( "light:on", function( event ) {
$( this ).removeClass( "off" ).addClass( "on" );
}).on( "light:off", function( event ) {
$( this ).removeClass( "on" ).addClass( "off" );
});
$( ".switch, .clapper" ).click(function() {
var room = $( this ).closest( ".room" );
room.find( ".lightbulb" ).trigger( "light:toggle" );
});
$( "#master_switch" ).click(function() {
var lightbulbs = $( ".lightbulb" );
// Check if any lightbulbs are on
if ( lightbulbs.is( ".on" ) ) {
lightbulbs.trigger( "light:off" );
} else {
lightbulbs.trigger( "light:on" );
}
});

请注意主开关的行为如何附加到主开关;灯泡的行为属于灯泡。

link 命名自定义事件

您可以对自定义事件使用任何名称,但您应该注意不要创建名称可能被未来的 DOM 事件使用的事件。出于这个原因,在本文中,我们选择为所有事件名称使用 light:,因为带有冒号的事件不太可能被未来的 DOM 规范使用。

link 回顾:.on().trigger()

在自定义事件的世界中,有两个重要的 jQuery 方法:.on().trigger()。在 事件 章节中,我们看到了如何使用这些方法来处理用户事件;对于本章,记住两件事很重要

  • .on() 方法将事件类型和事件处理函数作为参数。或者,它还可以将与事件相关的数据作为其第二个参数,将事件处理函数推送到第三个参数。传递的任何数据都将在事件对象的 data 属性中提供给事件处理函数。事件处理函数始终将事件对象作为其第一个参数接收。

  • .trigger() 方法将其事件类型作为参数。或者,它还可以采用一个值数组。这些值将在事件对象后作为参数传递给事件处理函数。

以下是在两种情况下使用 .on().trigger() 的示例,其中使用自定义数据

1
2
3
4
5
6
7
8
9
$( document ).on( "myCustomEvent", {
foo: "bar"
}, function( event, arg1, arg2 ) {
console.log( event.data.foo ); // "bar"
console.log( arg1 ); // "bim"
console.log( arg2 ); // "baz"
});
$( document ).trigger( "myCustomEvent", [ "bim", "baz" ] );

链接 结论

自定义事件提供了一种思考代码的新方式:它们强调行为的目标,而不是触发行为的元素。如果你一开始就花时间阐述应用程序的各个部分,以及这些部分需要表现出的行为,自定义事件可以为你提供一种强大的方式来“与”这些部分“对话”,无论是逐个对话还是批量对话。一旦描述了某个部分的行为,就可以轻松地从任何地方触发这些行为,从而可以快速创建和试验界面选项。最后,自定义事件可以通过明确元素与其行为之间的关系来提高代码的可读性和可维护性。