`
zzc1684
  • 浏览: 1201534 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

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完全学习手册1 源码

    10.2.5 使用JavaScript处理事件 271 10.3 标准事件模型 273 10.3.1 事件传播 273 10.3.2 注册事件处理程序 274 10.3.3 设置对象的事件处理程序 276 10.3.4 事件的模块和类型 276 10.3.5 Event接口和对象 278 10.4 IE...

    javascript完全学习手册2 源码

    10.2.5 使用JavaScript处理事件 10.3 标准事件模型 10.3.1 事件传播 10.3.2 注册事件处理程序 10.3.3 设置对象的事件处理程序 10.3.4 事件的模块和类型 10.3.5 Event接口和对象 10.4 IE事件模型 ...

    JavaScript详解(第2版)

    1.8 JavaScript和事件 9 1.9 标准化JavaScript和W3C 11 1.9.1 JavaScript对象 12 1.9.2 文档对象模型 12 1.10 关于浏览器 13 1.10.1 JavaScript的版本 14 1.10.2 你的浏览器遵循标准吗 16 1.10.3 ...

    ArcGIS 模型自定义路网导航工具

    通过上传自己的3D模型,可以根据模型自定义编辑模型内的导航路径,并转换为ArcGIS路网并可发布路网服务,结合ArcGIS JavaScript API 实现路网分析能力。该工具最主要是方便我们基于模型自定义一个路线,可以结合...

    JavaScript_从自定义动画到动画3D模型,本教程涵盖了所有内容.zip

    JavaScript

    《JavaScript学习指南(第2版)》[PDF]

     基于浏览器对象模型(BOM)、文档对象模型(DOM)以及所创建的自定义对象完成开发;  浏览器端的cookie及更新的客户端存储技术;  在Ajax应用程序中使用XML或JSON表示法的细节。本书遵循已被验证的学习法则,...

    js事件模型与自定义事件实例解析

    JavaScript 一个最简单的事件模型,需要有事件绑定与触发,还有事件删除。 var eventModel = { list: {}, bind: function () { var args = [].slice.call(arguments), type = args[0], handlers = args.slice...

    自定义HTML元素用于轻松展示3D模型

    自定义HTML元素用于轻松展示3D模型

    用于在HTML文档中呈现内联3D模型并允许使用CSS对其进行转换的自定义元素_JavaScript_下载.zip

    用于在HTML文档中呈现内联3D模型并允许使用CSS对其进行转换的自定义元素_JavaScript_下载.zip

    源文件程序天下JAVASCRIPT实例自学手册

    源文件程序天下JAVASCRIPT实例自学手册 第1章 JavaScript语言概述 1.1 JavaScript是什么 1.1.1 JavaScript简史 1.1.2 JavaScript有何特点 1.2 JavaScript能做什么 1.2.1 表单数据合法性验证 1.2.2 页面特效 1.2.3 ...

    JavaScript学习指南(第2版).pdf

    ● 基于浏览器对象模型(BOM)、文档对象模型(DOM)以及所创建的自定义对象完成开发; ● 浏览器端的cookie及更新的客户端存储技术; ● 在Ajax应用程序中使用XML或JSON表示法的细节。 本书遵循已被验证的学习法则...

    JavaScript完全自学宝典 源代码

    示例描述:介绍JavaScript文档对象模型。 5.1.html 使用DOM获取各级别节点。 5.2.html 使用DOM获取body元素。 5.3.html 获取元素的子节点。 5.4.html 改变div的内容。 5.5.html 获取表格第1行。...

    JavaScript基础和实例代码

    JavaScript电子书,包括了JavaScript的大部分知识,可以帮助读者快速入门。内容如下: 第1章 JavaScript语言概述 1.1 JavaScript是什么 1.1.1 JavaScript简史 1.1.2 JavaScript有何特点 1.2 JavaScript能做什么 ...

    JavaScript王者归来part.1 总数2

     13.5 回调与用户自定义事件   13.5.1 事件处理模式--一个实现简单事件处理模式的例子   13.5.2 用户事件接口的定义   13.5.3 事件代理和事件注册--一个实现标准事件接口的例子   13.5.4 标准模式--事件...

    javel:JavaScript JavaScript中简单,轻巧和可自定义的Laravel模型

    标枪 :wrapped_gift: 将普通JavaScript对象包装到可自定义的类似Laravel的模型中。 。安装npm i javel -D概述import Model from 'javel'class Article extends Model { /* ... */ }await Article . all ( { /* ...

    智能模型:JavaScript对象模型

    Javascript对象模型。 1Kb压缩 价值转换 值格式 值类型验证 价值内容验证(必填,自定义规则) 默认值 虚拟财产 现场直播活动 正确的文档^^ 体面的测试^^ 安装 安装npm软件包 npm install @jaysalvat/...

    JavaScript前端开发的核心语言前端开发的核心语言

    它可以通过操作DOM(文档对象模型来动态地修改网页的结构和布局,并且可以根据用户的行为实时地响应各种事件,如点击、标悬停、滚动等。这使得开发者可以轻松地为网页添加交互性和动态效果,提供更好的用户体验。 ...

    深入解析JavaScript框架Backbone.js中的事件机制

    事件模型及其原理 Backbone.Events就是事件实现的核心,它可以让对象拥有事件能力 var Events = Backbone.Events = { .. } 对象通过listenTo侦听其他对象,通过trigger触发事件。可以脱离Backbone的MVC,在自定义...

    JavaScript 浏览器对象模型BOM原理与常见用法实例分析

    本文实例讲述了JavaScript 浏览器对象模型BOM原理与常见用法。分享给大家供大家参考,具体如下: 什么是BOM BOM:Browser Object Model,浏览器对象模型 从上图也可以看出: window对象是BOM的顶层(核心)对象,...

Global site tag (gtag.js) - Google Analytics