10月阅读周·JavaScript异步编程设计快速响应的网络应用:深入理解JavaScript事件,jQuery自定义事件篇

举报
叶一一 发表于 2024/10/21 09:19:10 2024/10/21
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出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畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。