10月阅读周·JavaScript异步编程设计快速响应的网络应用:深入理解JavaScript事件,jQuery自定义事件篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》。
当前阅读周书籍:《JavaScript异步编程设计快速响应的网络应用》。
jQuery自定义事件
自定义事件是 jQuery 被低估的特性之一,它简化了强大分布式事件系统向任何Web应用程序的移植,而且无需额外的库。在jQuery中,可以使用trigger方法基于任意DOM元素触发任何想要的事件。
$('#tabby, #socks').on('meow', function () {
console.log(this.id + ' meowed');
});
$('#tabby').trigger('meow'); // "tabby meowed"
$('#socks').trigger('meow'); // "socks meowed"
如果以前用过DOM事件,则肯定熟悉冒泡技术。只要某个DOM元素触发了某个事件(譬如'click'事件),其父元素就会接着触发这个事件,接着是父元素的父元素,以此类推,一直上溯到根元素(即document),除非在这条冒泡之路的某个地方调用了事件的stopPropagation 方法。(如果事件处理器返回 false,则 jQuery会替我们自动调用stopPropagation方法。)但你是否也知道jQuery自定义事件的冒泡技术呢?举个例子,假设有个名称为“soda”的span元素嵌套在名称为“bottle”的div元素中,代码如下。
$('#soda, #bottle').on('fizz', function () {
console.log(this.id + ' emitted fizz');
});
$('#soda').trigger('fizz');
得到的输出如下:
soda emitted fizz
bottle emitted fizz
这种冒泡方式并非始终受人欢迎,从下面的tooltip(工具提示条)示例就能看到这一点。幸运的是,jQuery 同样提供了非冒泡式的triggerHandler方法。
示例:工具提示条
事件直观映射至页面元素之后,jQuery就成为分发这些事件的一种理想方式。举个例子,假设正在编写一个关于工具提示条的库,并希望任一时刻只能看到一个工具提示条。我们可能会简单地写下这行代码:
$('.tooltip').remove();
并将它添加到那个负责新添工具提示条的函数的开头。但后来我们又想独立出某些容器(譬如,当侧边栏显示新的工具提示条时,其他地方的工具提示条不受影响),该怎么办?如果反过来,又该怎么办?编写一个选择器来选中“那些类别为tooltip且不是sidebar后代的 DOM 元素”,这显然很复杂,而且会非常没有效率。如果允许独立容器作任意深度的嵌套,这个问题的难度还会呈指数级增长。
不过,利用事件逻辑而不是选择器逻辑来实现这一行为则会很容易。
// $container could be $('#sidebar') or $(document)
$container.triggerHandler('newTooltip');
$container.one('newTooltip', function () {
$tooltip.remove();
});
(请注意这里使用了 jQuery的 one 来代替 on。这两者的区别在于,one在触发处理器之后会自动将其删除。)
有了这两行代码之后,所有的工具提示条都会监听自己的容器,并且每当容器获得新工具提示条时就移除自己。这种优美、直接、有效的方式拯救了我们,让我们无需存储任何状态,也不用鼓弄那些复杂的选择器。(复杂选择器会让那些旧式浏览器慢得像乌龟爬——在不遍历整个文档的情况下,IE7 及更早版本甚至都无法选中类别为tooltip的所有DOM元素!)
请注意,实际上在这个案例中事件冒泡技术会破坏我们的意图:希望在侧边栏新建一个工具提示条时,只有那些监听侧边栏之'newTooltip'事件的工具提示条消失不见,而那些监听外围document元素的工具提示条不受影响。请始终认真思考这个问题:trigger或triggerHandler,到底哪一个才是完成该任务的合适工具?
jQuery自定义事件是PubSub模式的忤逆产物,因为这里由可选择的DOM 元素而不是脚本中的对象来触发事件。事件化模型更像是一种直观表达状态相关事件的方式,而 jQuery 的自定义事件允许直接通过DOM来表达DOM相关的事件,不必再把DOM变化的状态复制到应用程序的其他地方。请大方地取用这些特性,但要尽量避免依赖应用程序的标记语言结构——你肯定不希望下次修改设计的时候破坏自己的脚本。
总结
jQuery不仅能很好地响应浏览器提供的DOM事件,而且还非常适用于那些与DOM元素变化有关的分布式事件。事件化的对象与DOM元素的事件可以彼此完美互补,这有助于保持应用状态数据与应用视图相对于彼此的封装状态。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)