自定义事件很酷

Avatar of Chris Coyier
Chris Coyier 发表

DigitalOcean 为您的旅程各个阶段提供云产品。 立即开始使用 免费赠送 200 美元的信用额度!

假设您正在使用 jQuery 开发一个 Web 应用程序,并且需要编写一个适合 Web 应用程序需求的手风琴。 您决定将其做成一个插件。 这样,应用程序中任何需要手风琴的地方都可以加载此插件并将其调用到准备变为手风琴的语义标记上。 然后,您将得到一个漂亮的手风琴。

现在,另一个开发人员正在使用您的手风琴,他们希望能够将一些内容通过 AJAX 加载到手风琴的某个部分中,但前提是该部分已打开。 您共同决定代码应该分开。 手风琴工作方式的通用功能应该与特定于应用程序中一个页面上的一个手风琴的代码分开。

回调,传统方法

一种方法是在插件中编写“回调”。 另一位开发人员将指定一个函数的名称,当手风琴上发生某些操作时,她希望运行该函数。 因此,调用它可能类似于

$(".accordion").accordion({
  panelOpen: myPanelOpenCallback,
  panelClose: myPanelCloseCallback;
});

他们将自行创建这些回调函数

function myPanelOpenCallback() {
  // Do Ajax stuff 
}

然后插件本身将在其相关的内部函数中遵守这些回调

$.fn.accordion = function(options) {
    
	return this.each(function(i, el) {

	  var base = el;
	  
	  base.init = function() {
	  	// Do initialization stuff
	  };
	  
	  base.openPanel = function(panel) {
	  	// Open panel
		
		// Do callback
		options.panelOpen.call();
	  };
	  
	  base.closePanel = function(panel) {
	  	// Open panel
		
		// Do callback
		options.panelClose.call();
	  };
	  
	  base.init();
	       
	});
  
};

查看回调模型演示

自定义事件,更好的方法

现在假设第三位开发人员也参与进来,他们也希望编写一些 JavaScript 代码来响应面板打开。 为了便于用例,假设手风琴面板中的内容是设置,这位开发人员希望在打开或关闭键时自动保存这些设置。

现在我们处于一个有趣的境地。 我们已经为手风琴面板的打开和关闭定义了回调。 因此,在回调模型中,这些开发人员将不得不一起处理该回调并在该回调中运行他们的代码。 这并不算什么大问题,但现在我们被迫混合代码,而这可能并非理想。 请记住,我们一开始就是通过将特定功能分开来启动整个过程的。

这就是自定义事件非常棒的地方。 手风琴功能插件不会触发指定的回调,而是会触发自定义事件。 自定义事件就像其他任何事件(例如单击)一样,只是它们 **仅** 通过编程方式声明和调用。

首先,回调消失了,我们只需调用手风琴插件,无需回调

$(".accordion").accordion();

现在,在我们调用回调的地方,我们将触发我们的自定义事件。 基本上,只需想出一个有意义的名称(就像您为函数命名一样)。

// OUT
// options.panelOpen.call();

// IN
panel.trigger("panelOpen");

现在,其他开发人员可以将他们的代码绑定到此自定义事件并执行他们自己的操作。

$(".panel").on("panelOpen", function() {
   // Developer 1: do Ajax stuff
});

// Meanwhile, in another part of town...
$(".panel").on("panelOpen", function() {
   // Developer 2: do saving stuff
});

自由万岁! 功能分离万岁!

我认为自定义事件总的来说更好。 但是,我认为它们需要更多沟通。 您可能需要在某个地方写一些注释,解释哪些自定义事件被触发以及何时触发,并使它们易于发现。

查看自定义事件模型演示

更多信息

上面概述的场景非常简单。 以下两篇文章更深入地介绍了自定义事件,包括更复杂的示例和有关它们工作方式的更多信息。