被我拖延了将近一个月的javascript事件模型系 列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁 了一段时间,好在最近这些事情都一件件趋于平息,我也有了精力继续写文章。
这个自定义事件其实是挺让我纠结的,首先自己平时从未使用过,只是有一次遇到一个问题有人指点说可以用自定义事件,才对这个东西有了印象。在网上搜“javascript自定义事件”,发现也有不少文章在写,不过说实话让我佩服的却一篇也没找到,就连张鑫旭大哥写的漫谈javascript自定义事件也 把我看的云里雾里。陆续查阅了一些资料后越发觉得自定义事件这个东西真是个鸡肋,没什么用武之地。这也使我一度想放弃写这篇文章,但后来自己又进行了一些 思考,并有了一些新的想法,所以在此还是写出来与大家分享。本来想大手一挥书写标题“javascript自定义事件”,转而一想这个标题真是被用滥了, 满大街走的都是长一个样的,谁能认得我呀,亲,我跟他们可真的不太一样哦。所以前面加上了“我所理解的”,并不全是为标题突出,其实真的有很多自己的理 解。
一、什么是自定义事件
这个其实并不难理解,js中有很多的事件,如click(单击)、dbclick(双击)、mouseover(鼠标移上)等等,大部分是一些 鼠标或键盘事件,当然也还有其他的如文档的load,只不过我们平时更加关注前者,因为毕竟是要和用户打交道嘛,这些可以统称为DOM事件(都是发生在 DOM元素上)。何为自定义DOM事件呢?举个栗子:元素有单击、双击事件,我现在想定义一个三击事件,即元素被连续点击了三次,就给它起名字叫 tripleclick。这就是一个自定义的事件。再来个栗子:元素的内部html发生变化,我想监听到此事件,于是可以定义一个htmlchange事 件。概念就是这么回事。
既然有DOM事件,那有没有非DOM事件呢?动脑筋想一想。有了~前段时间刚好研究过history API,其中点击了浏览器后退按钮会触发popstate事件,这就是个非DOM事件。那我们可以自定义些什么非DOM事件呢?再开阔一下思 维,javascript好歹也是一门编程语言呀,除了操作DOM、BOM之外还有很多事情可以做呢。比如我写了一个dog对象,也可以给它自定义个事件 bark(狗叫),一旦发生了这个事件,我们可以捕捉到,在onbark处理函数中执行一些操作,如把dog给赶走。
那么,所谓自定义事件就是起个名字?这就完了?先埋个伏笔,后面来谈谈我的看法。
二、如何自定义事件
关于实现自定义事件的方式,我搜索中文的网页大概也就两种方式,而且就是那么几篇文章被抄来抄去,实在是乏味。总结一下:
第一种方式是自己模拟一个事件结构,其原理是这样的,我们平时监听事件的时候其实就是一种观察者模式,举个例子吧更明确些。
<input type="button" value="点我" onclick="clickhandler()" /> <script type="text/javascript"> function clickhandler(){ alert('点你怎么了!'); } </script>
在这里被观察的主体就是这个button,有一个handler订阅了它的点击事件,当被点击时,button会发布自己被点击的消息,handler接收到消息便开始执行处理函数。是相当标准的一个观察者模式。
照着这个思路,我们可以把整个过程用代码模拟出来,而不使用浏览器的事件机制,让这个button发布一点其他的消息,比如我们霸气的“三 击”,然后写一个handler来监听这个三击事件即可。具体的实现例子我就不写了,因为我觉得这个模拟的办法简直是太土了,根本拿不上台面,想研究的可 以看下这篇文章http://www.jb51.net/article/33697.htm 尽管我很恶心脚本之家这种随便剽窃别人文章的行为,但抱歉我真的找不到出处了。。。
看过了第一种土的掉渣的方式,我们再来看看高端洋气的写法。说白了,其实w3c已经定义了标准的自定义事件写法了。
第二种方式如下:
var e = document.createEvent('Event');//创建一个Event对象e e.initEvent('myevent',true,true);//进行事件初始化 var d1 = document.getElementById('d1');//获取DOM元素 d1.addEventListener('myevent',function(event){ alert(‘我监听到了自定义事件’+event.type); },false);//绑定监听器 d1.dispatchEvent(e);//触发该事件
使用标准方法还是相当简单的,首先利用document的createEvent方法可以创建一个事件对象,createEvent接收一个参 数表示事件的构造器,如Event、MouseEvent、UIEvent、CustomEvent,至于这些事件类都有哪些这里就不详细讲了,你可以查 看我之前写的系列,有提到相关内容可以追踪链接。然后使用initEvent函数进行事件的初始化,接收的参数分别表示事件的类型、是否冒泡、是否可以用 preventDefault()函数禁止默认行为,在这里你就可以为自定义事件起名字了。然后我们注册监听器并触发事件,这样d1便能监听到自己定义的 事件了,ok,就这么简单!
本来自定义事件的方式就该到此结束了,一个小小的意外,我搜到了一篇国外的文章,看到了如下字样:
来自mozilla开发者官网,说的就是上面的第二种方式。deprecated?啥意思?google之,藐视的意思!这种方式已经被藐视了哇!竟然还在国内的各网站中被转来转去,国外的同仁正在藐视我们。。。不能忍!赶快看看现在都用什么方式了。
第三种:
var event = new CustomEvent('build', { 'detail': elem.dataset.time });//区别就在这里~ elem.addEventListener('build', function (e) { ... }, false); elem.dispatchEvent(event);
原来是直接创建Event对象,取代了原来的document.createEvent(),而且事件的初始化工作也在这里完成了,不必调用 initEvent()了。嗯~不错,是能省一行代码。探讨为什么要这么写也没什么意义,咱跟着国际潮流走就是了。现在已经越来越明显,这个所谓的自定义 事件,其实与其他事件是同宗同源,只是名字(类型)不同罢了。
三、自定义事件实例
了解了这么多,你肯定也和我一样还在困惑,上面的东西都是纸上兵法,这自定义事件到底怎么用我还是不知道。比如我就想要一个tripleclick(三击)事件,具体该如何实现呢?下面就来实践一下,GO~
自定义事件的步骤我总结为“三板斧”,下面开始操练:
① 创建自定义事件
var e = new CustomEvent('tripleclick',{'detail':'somemsg'});//创建自定义事件tripleclick
② 在合适的时机触发事件
var counter = 0; var d1 = document.getElementById('d1'); d1.onclick = function(){ setTimeout(function(){counter=0;},500); if(++counter==3){ d1.dispatchEvent(e); } }
其实这第二步才是实现tripleclick事件的核心,首先声明一个计数器,每次元素点击便自增,当累计点击三次的时候将事件派发出去,即触 发事件。为了防止每次点击之间的间隔时间过长,每次点击后由一个延时函数进行清零,保证只有是连续点击才触发。代码不难理解。我也想在这里说说我的看法,自定义事件不单单是起个自定义名字,还要给这个事件加以描述,定义好它是在什么样的情况下发生。
在这里,tripleclick是依赖于click的,看上去更像是一个逻辑事件,非真正的事件。但由于我们的对象确实是 CustomEvent的实例,那它便无疑是一个货真价实的自定义事件。你可能会担心难道我们的自定义事件都要依赖于现有的事件?其实也未必,稍后会写另 外一个例子来说明。
③ 为事件注册监听函数
d1.addEventListener('tripleclick',function(event){ alert(‘我被三击了~’); },false);
在此处就可以把我们定义的tripleclick光明正大的写在addEventListener函数中了。
全部步骤就这些,完整的代码如下:
<div id="d1">有本事点我三次</div> <script type="text/javascript"> var d1 = document.getElementById('d1'); d1.addEventListener('tripleclick',function(event){ alert('我被三击了~'); },false); var e = new CustomEvent('tripleclick',{'detail':'somemsg'}); var counter = 0; d1.onclick = function(){ setTimeout(function(){counter=0;},500); if(++counter==3){ d1.dispatchEvent(e); } } </script>
你可以轻轻抖动三下手指,点击下面这个嚣张的div:
有点感觉了吧~不过这个三击确实有点小儿科,实际上能派上用场的概率基本为0,下面就来整点有用的东西,我们来实现一个htmlchange事件,即元素的内部html发生变化时触发该事件。这个东西在平时或许还真能用得着。
首先,事件的创建和监听与上面基本一样
var e2 = new CustomEvent('htmlchange',{'detail':'somemsg'}); d1.addEventListener('htmlchange',function(event){ alert('检测到html发生变化!'); },false);
然后,我们需要采用一个定时函数来不断检测d1内部的html,当发现与旧值不同时便派发htmlchange事件,代码如下:
var oldhtml = d1.innerHTML; setInterval(function(){ if(d1.innerHTML!==oldhtml){ d1.dispatchEvent(e2); oldhtml = d1.innerHTML; } },100);
三板斧完毕,来看看效果:
最慢能在0.1s内作出反应,你也可以把时间设置的更小一些。我们构想一个场景,你写的一个子页面A要被别人的页面B嵌套,并且B会修改A页面 中某个元素的内部html,A在无权干涉B中代码的情况下,就可以在自己页面中定义一个htmlchange事件,监听B对A的修改并作出处理。怎么样, 体会到自定义事件的威力了吧。
四、谈谈自定义事件的用武之地
看了很多纸上谈兵的介绍之后我就一直在想,自定义事件的研究和使用为何如此少?它的真正用处到底在哪里?难道真的是javascript中的鸡肋?
在第三节举出的两个实例或许能说明一点什么,至少它能帮我们扩展一下DOM事件,在当前已有的事件不能满足需求时,可以自己定义一个来使用。其 他的用途呢?此时我想到了开篇提到的观察者模式,我们认为浏览器对事件的处理是一种观察者模式,如果反过来呢,我想设计一种观察者模式,是否可以用自定义 事件来实现呢?主体需要发布的各种消息通过创建各种自定义事件来实现,对于消息的订阅则通过注册监听器来实现,岂不是利用现有资源便完成了一个观察者模 式,而不必再写那么多的代码去模拟。到这里我又情不自禁的想到了node.js,在node中,用事件驱动来完成代码逻辑,其事件是否跟这里的自定义事件 如出一辙?只是个猜测,我对node一知半解,真相也不得而知。
不过至少也可以得出一个结论,自定义事件并非鸡肋,站在设计模式或者是设计一个框架的角度来看,它的特性或许真是处理某类问题的灵丹妙药。
相关推荐
在JavaScript中实现自定义事件,我们可以借鉴ActionScript(AS)的一些概念,尽管JavaScript本身并不直接支持像AS那样的事件模型,但可以通过模拟来实现。 `BaseEvent.js`和`EventDispatcher.js`这两个文件很可能是...
JavaScript对象模型(Object Model)和执行模型是理解JavaScript工作原理的关键概念。JavaScript是一种基于原型的动态类型语言,其对象模型是其核心特性之一。本文将深入探讨JavaScript的对象模型和执行模型,以及...
JavaScript还允许创建和触发自定义事件,使用`new Event`或`new CustomEvent`构造函数创建事件,然后通过`dispatchEvent`方法触发。 七、现代事件API 除了传统的DOM事件模型,还有更现代的事件API,如`...
本文将深入探讨如何为jQuery添加自定义事件机制,这将帮助开发者扩展jQuery的功能,实现更加个性化的交互逻辑。 首先,我们要了解jQuery的事件系统是基于浏览器的事件模型构建的。默认情况下,jQuery提供了如click...
本文将深入探讨JavaScript的对象模型以及执行模型的相关知识点,帮助读者更好地理解并应用这些核心概念。 #### 二、JavaScript对象模型概述 **对象模型**是指在JavaScript中定义和操作对象的一套规则。在...
"WEB页编程技巧──JavaScript事件的应用.pdf" 本文档主要介绍了...本文档对JavaScript事件和事件驱动编程进行了详细的介绍,并提供了WEB页编程示例,以帮助读者更好地理解和应用JavaScript事件驱动编程技术。
通过这样的自定义事件模型,开发者可以更好地理解和控制事件处理流程,同时也为跨浏览器的兼容性问题提供了自定义解决方案。然而,对于复杂的应用场景,仍然推荐使用原生的DOM2级事件模型或者更高级的事件库,如...
- 自定义事件:开发者可以通过`new Event`或`new CustomEvent`创建自定义事件。 三、事件处理函数 1. 内联处理:通过HTML属性,如`onclick="functionName()"`,但不推荐,因为不利于代码分离和维护。 2. 事件监听...
用户可以通过自定义事件处理器来改变默认的行为,例如,一个链接点击事件默认会跳转到链接指向的页面,但是通过JavaScript,可以轻松地编写自定义事件处理器,以替代这一默认行为。以下是一个简单的示例: ```html ...
本文将深入探讨JavaScript事件的各个方面,帮助开发者更好地理解和应用这些关键概念。 一、事件概述 事件是用户或浏览器执行的特定动作,如点击按钮、滚动页面、提交表单等。在JavaScript中,我们可以通过监听这些...
另一种解决方案是使用自定义事件处理函数,将旧的事件处理函数保存并调用,同时确保新添加的函数能够正确执行。这通常通过在对象的内部属性中存储事件处理函数来实现。然而,删除事件处理函数时需要注意,直接将事件...
综上所述,"ppk关于javascript事件的讲解"教程可能涵盖了这些核心概念:事件模型、事件处理函数、事件冒泡与捕获、事件委托,以及内置和自定义事件的使用。通过学习这个教程,你将能够熟练地运用JavaScript事件来...
这个名为"JavaScript_从自定义动画到动画3D模型,本教程涵盖了所有内容.zip"的压缩包文件,显然是一个关于JavaScript动画技术的深度学习资源,特别是涉及到从基本的自定义动画到复杂的3D模型动画的实现。 首先,...
JavaScript中的自定义事件是Web开发中非常重要的一个概念,允许开发者创建和触发在浏览器中具有特定行为的事件。这些事件可以包含更多的上下文信息,并且可以根据特定的需要被触发,而无需等待浏览器的默认行为。...
在IT领域,基于JavaScript的可视化流程自定义设计器是一种强大的工具,它允许用户通过图形界面来构建、编辑和管理流程图。这种技术广泛应用于业务流程管理(BPM)、工作流自动化、系统集成等领域,使得非技术人员也...
自定义事件处理函数是对传统事件绑定的一种改进,通过自定义的函数来封装事件绑定的逻辑,解决了覆盖问题、可读性问题和this传递问题。 ```javascript function addEvent(obj, type, fn) { var saved = obj['on' +...
综上所述,自定义事件是JavaScript编程中一个重要的特性,它有助于创建可复用、可扩展的组件,并促进代码的模块化。通过理解并熟练运用自定义事件,开发者可以更好地控制应用程序的流程,提升用户体验。
此外,本书还会涉及JavaScript中的事件处理、DOM操作和BOM(浏览器对象模型)使用,这些都是创建动态网页的关键技术。JavaScript的异步编程,如回调函数、Promise和async/await,也会有详尽的解析,这些内容对于理解...
在"JavaScript_LLM自定义聊天机器人控制台.zip"这个压缩包中,我们可以推测其主要内容是关于如何使用JavaScript来构建一个聊天机器人的控制台。下面将详细探讨JavaScript在聊天机器人开发中的应用和相关知识点。 1....
本压缩包文件“Javascript API for ArcGIS Server对象模型图.rar”包含了关于这个API的详细对象模型图,对于理解和学习JavaScript API的使用非常有帮助。 1. **对象模型图**:对象模型图是API中各种对象、类和方法...