阅读目录

  • 1. 自定义事件
  • 2. 事件命名空间
  • 3. 命名空间的匹配规则
  • 4. 命名空间的冒泡
  • 5. 文中小结
  • 6. off方法中的使用
  • 7. 本文小结

jquery现在的事件API:on,off,trigger支持带命名空间的事件,当事件有了命名空间,就可以有效地管理同一事件的不同监听器,在定义组件的时候,能够避免同一元素应用到不同组件时,同一事件类型之间的影响,还能控制一些意外的事件冒泡。在实际工作中,相信大家都用的很多,但是不一定了解它的所有细节,至少我有这样的经验,经常在碰到疑惑的时候,还得重新写例子去验证它的相关作用,所以本文想把事件命名空间相关的细节都梳理出来,将来再犯迷糊的时候可以回来翻着看看以便加深对它的理解和运用。

在详细了解命名空间之前,得先认识下什么是自定义事件,因为命名空间可以同时应用于自定义事件和浏览器默认事件当中。

1. 自定义事件

我们在定义组件的时候,浏览器的默认事件往往不能满足我们的要求,比如我们写了一个树形组件,它有一个实例方法init用来完成这个组件的初始化工作,在这个方法调用结束之后,我们通常会自定义一个init事件,以便外部可以在树组件初始化完成之后做一些回调处理:

+ View code

以上代码中.on('init',…)中的init就是一个类似click这样的自定义事件,该代码运行结果如下

 
自定义事件的使用就跟浏览器默认事件的使用没有任何区别,就连事件冒泡和阻止事件默认行为都完全支持,唯一的区别在于:浏览器自带的事件类型可以通过浏览器的UI线程去触发,而自定义事件必须通过代码来手动触发: 

2. 事件命名空间

事件命名空间类似css的类,我们在事件类型的后面通过点加名称的方式来给事件添加命名空间:

+ View code

以上代码中.on('init.my.tree',…)通过.my和.tree给init这个事件添加了2个命名空间,注意命名空间是类似css的类,而不是类似java中的package,所以这两个命名空间的名称分别是.my和.tree,而不是my和my.tree,注意命名空间的名称前面一定要带点,这个名称在off的时候可以用到。在监听和触发事件的时候带上命名空间,当触发带命名空间的事件时,只会调用匹配该命名空间的监听器。所以命名空间可以有效地管理同一事件的不同监听器,尤其在定义组件的时候可以有效地保证组件内部的事件只在组件内部有效,不会影响到其它组件。

现在假设我们不用命名空间,同时定义两个组件Tree和Dragable,并且同时对#tree这个元素做实例化,以便实现一棵可以拖动的树:

+ View code

结果会发现Tree的onInit回调被调用两次: 
 
根本原因就是因为#tree这个元素被应用到了多个组件,在这两个组件内部对#tree这个元素定义了同一个名称的事件,所以后面实例化的组件在触发该事件的时候也会导致前面实例化的组件的同一事件再次被触发。通过命名空间就可以避免这个问题,让组件各自的事件回调互不影响:

+ View code

这样tree实例的onInit就不会被调用2次了:

3. 命名空间的匹配规则

在第2部分的举例当中,触发带命名空间的事件时,触发方式是: 
 
然后就会调用这里监听的回调: 
 
如果把触发方式改一下,不改监听方式,改成以下三种方式的一种,结果会怎么样呢:

+ View code

答案是该监听回调依然会被调用。这个跟命名空间的匹配规则有关,为了说明这个规则,可以用以下的这个代码来测试:

+ View code

初始化效果如下: 
  
依次点击界面上的按钮(不过点击按钮前得先刷新页面,这样的话各个按钮效果才不会混在一起),界面打印的效果如下: 
 
 
 
 

以上的测试代码一共给$p元素的click事件定义了4个命名空间,然后针对不同的命名空间数量,添加了五个监听器,通过外部的按钮来手动触发各个带命名空间的事件,从最后的结果,我们能得出这样一个规律: 
1)当触发不带命名空间的事件时,该事件所有的监听器都会触发;(从最后一个按钮的测试结果可看出) 
2)当触发带一个命名空间的事件时,在监听时包含该命名空间的所有监听器都会被触发;(从第4个按钮的测试结果可看出) 
3)当触发带多个命名空间的事件时,只有在监听时同时包含那多个命名空间的监听器才会被触发;(从第2,3个按钮的测试结果可看出) 
4)只要触发带命名空间的事件,该事件不带命名空间的监听器就不会被触发;(从1,2,3,4个按钮可看出) 
5)2跟3其实就是一个,2是3的一种情况

这个规律完全适用于浏览器默认事件和自定义事件,自定义事件的测试可以用下面的代码,结论是一致的:

+ View code

4. 命名空间的冒泡

为了说明命名空间的冒泡机制,需要把前面的测试代码改一改,并且以自定义事件来说明,测试代码如下:

+ View code

初始化效果如下: 
 
在这个测试中,点击按钮的时候触发的并不是$p元素的事件,而是$c元素的事件,$p是$c的父元素,上图中整个长方形容器就是$p元素,右边的正方形容器就是$c元素。当我们依次点击上面五个按钮的时候(还是采取刷新一次点一个按钮的方式),界面打印的效果如下: 
 
 
 
 

从这个测试结果来看,我们可以得出一个结论:jquery提供的事件机制,当子元素的带命名空间的事件冒泡到父级元素时,会以同样的命名空间触发父级元素的同一事件,为了方便起见,可以把这种冒泡机制称为带命名空间的冒泡。意味着当子元素的事件冒泡到父级元素时,只有那些满足该事件匹配规则的父级监听器才会被调用。

浏览器默认事件的冒泡也与自定义事件的机制相同,可以用下面的代码测试:

+ View code

需要特别注意的是:浏览器的默认事件能通过鼠标或键盘等操作,由浏览器UI线程自动触发的,而且只要是浏览器自己触发的事件,是不会带命名空间的。这样的话,只要浏览器在子元素自动触发了默认事件,那么子元素以及父元素所有的监听器都会执行,有时候这并不一定是你期望的,所以最好在开发组件的时候始终加命名空间来触发或者添加监听,这样就能屏蔽掉浏览器自动触发给组件带来的影响。

5. 文中小结

通过第3和第4部分,可以发现jquery的事件机制,纵向是一种带命名空间的冒泡机制,横向是一种按照命名空间匹配规则的管理方式,如下图所示:

综合起来,一个元素上的某个事件监听器如果要被触发的话,一共有以下几种情况:

1)直接在该元素上触发了该事件,通过命名空间匹配规则被触发; 
2)由子元素的相关事件冒泡到该元素,再通过匹配规则触发; 
3)如果是浏览器默认事件,还会由浏览器自动触发,不过浏览器自动触发最终还是要体现到冒泡规则和匹配规则上来。

6. off方法中的使用

jquery中在移除事件监听的时候,有多种方式,可以不带命名空间只通过事件类型来移除:

+ View code

也可以通过带命名空间的事件类型来移除:

+ View code

还可以只按命名空间来移除:

+ View code

为了更清楚地说明这三种移除方式的效果和规律,可以以下代码来测试

+ View code

初始化界面效果为: 
 
在这个测试中,为$p元素的两种事件click和hello各添加了五个监听器,命名空间的的设置还与前面的类似,hello事件在click事件不带命名空间的回调里被触发,提供了9个按钮分别用来测试不同的off事件的方式最后的结果。测试的方法是依次点击按钮(为了不让各个测试的结果互相影响,点击前还是得先刷新页面),点完按钮后,再点击一下$p元素,就是那个灰色边框的容器。只有第五个按钮不需要做第二次$p元素的点击,因为它已经把$p的click事件监听全部移除了,各个按钮的测试结果如下:

 
结果:click.n1.n2.n3.n4的监听没有被调用,hello事件不受影响。 
 
结果:click.n1.n2.n3.n4和click.n1.n2.n3的监听没有被调用,hello事件不受影响。 
 
结果:click.n1.n2.n3.n4和click.n1.n2.n3和click.n1.n2的监听没有被调用,hello事件不受影响。 
 
结果:click.n1.n2.n3.n4和click.n1.n2.n3和click.n1.n2和click.n1的监听没有被调用,hello事件不受影响。 
 
结果:所有click事件的回调都没有调用,hello事件不受影响。

综合以上的测试结果,可以得出的结论是: 
1)当通过一个或多个命名空间结合事件类型来移除的时候,只会把该事件的在添加监听的时候包含那些命名空间的监听器移除,不会影响该事件类型的其它监听器以及其它事件类型。比如移除click.n1.n2,会把click.n1.n2,click.n1.n2.n3还有click.n1.n2.n3.n4都移除,但是click.n1 , click 还有hello事件都不受影响。 
2)当通过事件类型来移除的时候,会把该事件的所有监听器都移除。

再看从第6个按钮开始的测试: 
 
结果:移除了click.n1.n2.n3.n4和hello.n1.n2.n3.n4,其它事件监听不受影响。 
 
结果:移除了click.n1.n2.n3.n4,click.n1.n2.n3和hello.n1.n2.n3.n4,hello.n1.n2.n3,其它事件监听不受影响。 
 
结果:移除了click.n1.n2.n3.n4,click.n1.n2.n3,click.n1.n2和hello.n1.n2.n3.n4,hello.n1.n2.n3,hello.n1.n2,其它事件监听不受影响。 
 
结果:移除了hello和click事件所有的带命名空间的监听。

综合最后这部分的测试结果,可以得出的结论是:

通过命名空间移除监听的时候,会影响所有的事件类型,会把所有事件类型的在添加监听的时候包含那些命名空间的监听器全部移除掉。比如最后的off(.n1),就把click和hello事件的所有带.n1这个命名空间的监听移除掉了。

7. 本文小结

本文花了大量的测试去了解命名空间在事件触发和事件冒泡以及移除监听时候的特性,内容虽然非常之多,但是已经充分达到了本文的最终目的,就是要把命名空间在事件管理里面的细节都梳理清楚,文中各个部分的核心内容最后都有简短的结论,将来有需要的时候可以直接通过结论来解除自己的疑惑,希望能给大家带来一些帮助,谢谢阅读:)

如果您觉得本文对你有用,不妨帮忙点个赞,或者在评论里给我一句赞美,小小成就都是今后继续为大家编写优质文章的动力,流云拜谢! 欢迎您持续关注我的博客:)

作者:流云诸葛

出处:http://www.cnblogs.com/lyzg/

jquery的事件命名空间详解相关推荐

  1. 委托与事件代码详解与(Object sender,EventArgs e)详解

    委托与事件代码详解 using System; using System.Collections.Generic; using System.Text; namespace @Delegate //自 ...

  2. jQuery.extend 函数使用详解

    jQuery.extend 函数使用详解 一.总结 一句话总结: jquery $.extend的作用就是:用于将一个或多个对象的内容合并到目标对象:$.extend( target [, objec ...

  3. jQuery 表单验证插件,jQuery Validation Engine用法详解

    jQuery 表单验证插件,jQuery Validation Engine用法详解 功能强大的 jQuery 表单验证插件,适用于日常的 E-mail.电话号码.网址等验证及 Ajax 验证,除自身 ...

  4. 最全的jquery datatables api 使用详解

    https://www.cnblogs.com/amoniyibeizi/p/4548111.html 最全的jquery datatables api 使用详解 学习可参考:http://www.g ...

  5. 【转】4.1触碰jQuery:AJAX异步详解

    传送门:异步编程系列目录-- 示例源码:触碰jQuery:AJAX异步详解.rar AJAX 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 X ...

  6. jQuery form插件使用详解

    点击打开: jquery选择器全解 jquery中的style样式操作 jquery中的DOM操作 jquery中的事件操作全解 jquery中的动画操作全解 jquery中ajax的应用 自定义jq ...

  7. jquery.uploadify php,jquery插件uploadify使用详解

    这次给大家带来jquery插件uploadify使用详解,jquery插件uploadify使用的注意事项有哪些,下面就是实战案例,一起来看一下. 有时项目中需要一个文件批量上传功能时,个人认为upl ...

  8. plupload怎么设置属性_jquery上传插件:plupload事件参数说明详解

    jquery上传插件:plupload事件参数说明详解 2018-12-01 本篇重点说明一下plupload的事件参数.并用2个例子说明一下绑定事件. 1.plupload参数说明: Browse_ ...

  9. 委托与事件代码详解与(Object sender,EventArgs e)

    http://apps.hi.baidu.com/share/detail/30334344 委托与事件代码详解与(Object sender,EventArgs e)详解 2008-02-04 21 ...

  10. 请求对象触碰jQuery:AJAX异步详解

    最近一直在研究请求对象之类的问题,现在正好有机会和大家讨论一下. 传送门:异步编程系列目录-- 示例源码:触碰jQuery:AJAX异步详解.rar AJAX 全称 Asynchronous Java ...

最新文章

  1. 让浏览器判断html为手机页面,判断是从手机端还是客户端访问的页面,判断浏览器类型...
  2. python解释器运行代码-python解释器怎么运行
  3. UA MATH571B 试验设计 Quarter 2-level析因设计
  4. 全球及中国黑胡椒粉行业竞争规划与未来发展趋势预测报告2022-2028年版
  5. Markovs Chains采样
  6. 2021-07-06-Intellij IDEA新建项目时JDK以及模块语言等级(language level)默认为1.8或1.5,每次创建新项目都需要重新更改
  7. 配置阿里云docker加速与云镜像配置
  8. 5G关键技术:大规模多天线技术现状及研究点介绍
  9. Nexus私服下载及安装
  10. 台式电脑主机前面耳机插孔没声音的解决方法
  11. 电路交换、报文交换和分组交换的区别
  12. UE-战斗无止境的UI实现
  13. 基于ElasticsearchRepository进行简单封装实现非空更新,saveOrUpdate[笔记]
  14. RPM(软件包管理器)和YUM 软件仓库
  15. redis服务器cpu100%的原因和解决方案
  16. Class类是什么?
  17. 内存不能为read修复方法
  18. 苹果x充电慢是什么原因_苹果手机充不进去电?为什么?什么原因?怎么解决?...
  19. Python生物统计学基础教程
  20. persevere的用法_词汇精选:persist的用法和辨析 - 英语讨论网

热门文章

  1. 破土Plan遇到的keng
  2. Golang 函数耗时统计
  3. 复权、前复权和后复权
  4. element-ui 实现图标选择器
  5. 计算机网络 可靠数据传输原理——从rdt协议到GBN到SR
  6. 颜色空间(RGB、YUV、YIQ、CMY)
  7. luogu_1378 油滴扩展
  8. MAC系统下测试IP+端口
  9. python 滚动字幕_python – 在PyQt中滚动文本?
  10. windows时间同步脚本