JavaScript 自定义事件之我见

作者:小前端 时间:2024-04-10 10:50:01 

事件

技术一般水平有限,有什么错的地方,望大家指正。

事件就是用户和浏览器交互的一种途径。假如一个用户注册的功能,我们在填写完基本信息之后,点击提交按钮就可以实现注册功能,要想完成这个功能所需要的就是点击事件。我们预先定义好操作行为,在用户点击提交按钮时就执行我们预先定好的行为,在本例中我们的代码逻辑一般就是收集用户填写信息,验证信息合法性,利用AJAX与服务器交互。

这个过程就好像我们平时封装函数然后调用函数一样,事件其实也就类似函数定义函数调用这样的一个过程,只不过事件函数的调用是由用户的一些操作来告知浏览器,让浏览器在去调用函数的。

首先浏览器已经给我们提供了一列的事件,包括click,keydown等等,为什么还需要自定义事件呢?其实就是对我们的行为进行更准确的描述。以上面的用户注册为例我们可以定义一个名为saveMessage的事件,在点击提交按钮时触发这个事件,好像看起来更加直观一些,不过这看起来和普通的函数调用没什么区别,仔细想了想函数调用和事件触发的区别就是由我们自己执行的函数就是函数调用,不是由我们执行的函数就是事件触发。看下面的代码:


window.onload = function(){
var demo = document.getElementById("demo");
demo.onclick = handler;
function handler(){
 console.log("aaa");
}
}

在我们点击按钮的时候就会打印aaa,而且很明显的可以看出函数并不是由我们调用的而是由浏览器来执行的,如果我们直接调用函数handler()一样可以打印aaa但这是由我们调用的所以是函数调用。

自定义事件的作用

自定义事件就是我们按照浏览器对事件的机制来自定义的函数。自定义事件,可以对我们的处理函数带来更好的说明,也可以为我们的插件带来更好的处理流程。假如我们又一个这样的需求:从服务器端拉取一组数据然后在HTML中显示成列表,然后标识出第一条数据,假如我们利用一个现有的处理函数,我们可能会这样来写:


dataTable("url");
$("table").find("input[type='checkbox']:first").prop("checked",true);

这是不能达到我们目的的因为JS是单线程的而AJAX是异步的,当代码$("table").find("input[type='checkbox']:first").prop("checked",true)执行的时候,我们需要的数据还没有获取到。我们去修改插件的内部实现显然是不明智的,一个可以被人接受的插件必然是有合理的回调函数(或者自定义事件)的,假如现在有一个列表绘制成功的回调函数,我们就可以把这个回调函数看做是一个事件,我们可以对这个事件添加事件操作,定义好处理函数,然后在列表绘制成功时让插件来执行这个处理函数。

自定义事件实现

我们模拟浏览器原生的事件来实现自定义事件(en:自定义事件名称,fn:事件处理函数,addEvent:为DOM元素添加自定义事件,triggerEvent:触发自定义事件):


window.onload = function(){
var demo = document.getElementById("demo");
demo.addEvent("test",function(){console.log("handler1")});
demo.addEvent("test",function(){console.log("handler2")});
demo.onclick = function(){
 this.triggerEvent("test");
}
}
Element.prototype.addEvent = function(en,fn){
this.pools = this.pools || {};
if(en in this.pools){
 this.pools[en].push(fn);
}else{
 this.pools[en] = [];
 this.pools[en].push(fn);
}
}
Element.prototype.triggerEvent = function(en){
if(en in this.pools){
 var fns = this.pools[en];
 for(var i=0,il=fns.length;i<il;i++){
  fns[i]();
 }
}else{
 return;
}
}

由我们自己执行的函数是函数调用,非我们执行的函数我们可以叫做触发事件,既然函数不是由我们调用的,那么调用者怎样知道调用哪些函数就是一个问题了,所以就需要在添加事件函数和触发事件函数之间加上一些约束了,那就是两者之间有一个都能访问到的事件池,添加事件时把事件及对应的处理函数放在这个池子里,当满足触发条件时就去池子里找到要触发的事件,执行对应的处理函数,所以就有了我们上面的那一段代码。

对同一个功能(事件)可能有很多个处理函数,所以我们就需要一个集合去存储这些处理函数,这时我们应该反映出两个方案JSON或者数组,JSON的结构是key:value,对于处理函数来说名字是没有什么作用的所以我们用数组来保存处理函数,这组函数是处理什么功能的,所以我们还需要对这组处理函数由一个说明这时候就需要JSON了-->{eventName:[]}。

以简化的BootStrap模态窗来演示自定义事件的作用:


window.onload = function(){
var show = document.getElementById("show");
var hide = document.getElementById("hide");
var content = document.getElementById("content");
show.onclick = function(){
 content.modal("show");
}
hide.onclick = function(){
 content.modal("hide");
}
content.addEvent("show",function(){alert("show before")});
content.addEvent("shown",function(){
 document.getElementById("input").focus();
 alert("show after");
});
}
;(function(ep){
ep.addEvent = function(en,fn){
 this.pools = this.pools || {};
 if(en in this.pools){
  this.pools[en].push(fn);
 }else{
  this.pools[en] = [];
  this.pools[en].push(fn);
 }
}
ep.triggerEvent = function(en){
 if(en in this.pools){
  var fns = this.pools[en];
  for(var i=0,il=fns.length;i<il;i++){
   fns[i]();
  }
 }else{
  return;
 }
}
ep.modal = function(t){
 switch(t){
  case "show":
   this.triggerEvent("show");
   this.style.display = "block";
   setTimeout(function(){this.triggerEvent("shown")}.bind(this),0);//该定时器主要是为了在视觉上先看见content,在弹出消息
   break;
  case "hide":
   this.style.display = "none";
   break;
  default:
   break;
 }
}

}(Element.prototype));

我们可以预先定义好在弹窗出现之前和出现之后的处理函数,当弹窗触发对应事件的时候就执行对应的处理函数。

来源:http://www.cnblogs.com/shinhwazt/p/5989889.html

标签:自定义事件
0
投稿

猜你喜欢

  • Python中工作日类库Busines Holiday的介绍与使用

    2023-01-30 23:59:04
  • python实现翻转棋游戏(othello)

    2022-06-02 10:40:19
  • Python使用struct处理二进制(pack和unpack用法)

    2022-12-23 08:27:56
  • django基于restframework的CBV封装详解

    2021-09-25 20:25:25
  • 解决IE下提示“无法打开Internet站点 已终止操作”的错误

    2009-03-04 12:04:00
  • 如何使用五行Python代码轻松实现批量抠图

    2023-10-06 08:05:20
  • 如何运行Python程序的方法

    2023-01-13 07:56:03
  • Python实现的批量下载RFC文档

    2021-11-25 02:54:48
  • Python+Opencv识别两张相似图片

    2022-11-07 09:12:55
  • 基于keras中import keras.backend as K的含义说明

    2023-04-28 08:43:27
  • vue实现选择商品规格功能

    2024-05-13 09:37:55
  • 解读MySQL的InnoDB引擎日志工作原理

    2011-01-04 19:59:00
  • Windows下MySQL 5.6安装及配置详细图解(大图版)

    2024-01-24 06:05:52
  • python调用DLL与EXE文件截屏对比分析

    2022-06-01 08:19:15
  • Bootstrap导航栏各元素操作方法(表单、按钮、文本)

    2023-08-15 05:14:27
  • 解决Python3中二叉树前序遍历的迭代问题

    2022-04-11 09:05:24
  • ASP利用Google实现在线翻译功能

    2010-03-07 17:28:00
  • c# 获取数据库中所有表名称的方法

    2024-01-16 18:41:33
  • MySQL的远程连接出现错误提示分析

    2011-07-01 11:34:00
  • 在python中bool函数的取值方法

    2021-10-06 00:47:37
  • asp之家 网络编程 m.aspxhome.com