理解的javascript自定义事件
理解的javascript自定义事件
被我拖延了将近一个月的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自定义事件的更多相关文章
- Javascript事件模型系列(四)我所理解的javascript自定义事件
被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁了一 ...
- javascript:自定义事件初探
javascript:自定义事件初探 http://www.cnblogs.com/jeffwongishandsome/archive/2008/10/27/1317148.html
- Javascript自定义事件功能与用法实例分析
原文地址:https://www.jb51.net/article/127776.htm 本文实例讲述了javascript自定义事件功能与用法.分享给大家供大家参考,具体如下: 概述 自定义事件很难 ...
- javascript 自定义事件 发布-订阅 模式 Event
* javascript自定义事件 var myEvent = document.createEvent("Event"); myEvent.initEvent("myE ...
- JavaScript自定义事件 - createEvent()、initEvent()和dispachEvent()
在学习目标事件的方法的时候,接触到了dispatchEvent()方法.度娘查一查,这是一个事件触发器,事件触发器其实就是触发事件的东西. 通常情况下,我们触发事件都是在交互中触发的事件,例如点击按钮 ...
- 高级功能:很有用的javascript自定义事件
之前写了篇文章<原生javascript实现类似jquery on方法的行为监听>比较浅显,能够简单的使用场景. 这里的自定义事件指的是区别javascript默认的与DOM交互的事件,比 ...
- JavaScript自定义事件
很多DOM对象都有原生的事件支持,向div就有click.mouseover等事件,事件机制可以为类的设计带来很大的灵活性,相信.net程序员深有体会.随着web技术发展,使用JavaScript自定 ...
- Javascript 自定义事件 (custom event)
Javascript 中经常会用到自定义事件.如何创建一个简单的自定义事件呢?在创建自定义的事件之前,我们应该考虑一下和事件有关的东西.例如 click 事件,首先我们要能注册一个click事件(在一 ...
- JavaScript自定义事件,动态添加属性
根据事件的不同,可用的自定义方法也不同. document.createEvent('Event'); 实现主要有4个步骤: 1.创建事件. 2.初始化事件(三个参数:事件名,是否起泡,是否取消默认触 ...
随机推荐
- HDU4405-Aeroplane chess(可能性DP需求预期)
Aeroplane chess Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 4915 Parenthese sequence(模拟)2014多培训学校5现场
Parenthese sequence Time Limit: ...
- 它们的定义app.config中间section节点和在执行中使用
如果现在我们需要在app.config一个节点的在下面的例子中,定义,我们需要如何进行操作? <configSections> <section name="integra ...
- 管理员控制Windows Service
C# 以管理员方式启动Winform,进而使用管理员控制Windows Service 问题起因: 1,) 问题自动分析Windows服务在正常运行时,确实会存在程序及人为原因导致该服务停止.为了 ...
- 【百度地图API】暑假放假回老家——城市切换功能
原文:[百度地图API]暑假放假回老家--城市切换功能 任务描述: 酸奶小妹放寒假啦,要从北京呼啦一下飞回重庆呢.现在百度地图API上不能直接切换城市,怎么办呢? 如何实现: 利用API先搜索到要去城 ...
- Largest Rectangular Area in a Histogram
题目地址:https://oj.leetcode.com/problems/largest-rectangle-in-histogram/ ,刚開始事实上没做这个题,而是在做https://oj.le ...
- oracle 电子商务解决方案讲义
1. 电商营销(CRM) - 高端客户体验 2. 当当网李国庆做 "千千面"购物体验 3. 所使用的唯一的产品oracle的CRM 4. 个人的事情.谁在世界上是用户体验. 5. ...
- Android安卓安全审计mobiseclab
关于安卓上的app分析,有非常多的本地化软件能够胜任, 只是,今天给大家介绍一款在线的安全审计,恶意软件(android app)检測和分析工具,mobiseclab, 由于看到国内对此工具的介绍比較 ...
- c#-Artificial Intelligence Class
NET Artificial Intelligence Class http://www.codeproject.com/KB/recipes/aforge_neuro/neuro_src.zip
- PHP: 判断是否是JSON数据
原文:PHP: 判断是否是JSON数据 首先要记住json_encode返回的是字符串, 而json_decode返回的是对象. 判断数据不是JSON格式: function is_not_json( ...