MyException - 我的异常网
当前位置:我的异常网» JavaScript » Javascript事件模型系列(四)小弟我所理解的javasc

Javascript事件模型系列(四)小弟我所理解的javascript自定义事件

www.MyException.Cn  网友分享于:2014-04-29  浏览:10次
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一知半解,真相也不得而知。

  不过至少也可以得出一个结论,自定义事件并非鸡肋,站在设计模式或者是设计一个框架的角度来看,它的特性或许真是处理某类问题的灵丹妙药。

文章评论

团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
编程语言是女人
编程语言是女人
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
鲜为人知的编程真相
鲜为人知的编程真相
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
中美印日四国程序员比较
中美印日四国程序员比较
为什么程序员都是夜猫子
为什么程序员都是夜猫子
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员都该阅读的书
程序员都该阅读的书
 程序员的样子
程序员的样子
旅行,写作,编程
旅行,写作,编程
代码女神横空出世
代码女神横空出世
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
那些争议最大的编程观点
那些争议最大的编程观点
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
程序员和编码员之间的区别
程序员和编码员之间的区别
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
老程序员的下场
老程序员的下场
我是如何打败拖延症的
我是如何打败拖延症的
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员应该关注的一些事儿
程序员应该关注的一些事儿
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
一个程序员的时间管理
一个程序员的时间管理
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
Java程序员必看电影
Java程序员必看电影
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
每天工作4小时的程序员
每天工作4小时的程序员
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
漫画:程序员的工作
漫画:程序员的工作
10个调试和排错的小建议
10个调试和排错的小建议
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有