谈一谈Web中的事件

简介: 谈一谈Web中的事件

640.jpg



••••   写在前面  ••••


在我之前的一篇文章《前端开发中的Error以及异常捕获》中,我提到【重写了 addEventListener 方法过后, React无法正常工作,且无任何报错】的问题。经过5个小时左右的折腾,我终于找到了原因,这里就不细说了,大概就是我重写了 addEventListener 而忽略了 removeEventListener ,添加的事件无法被正确的移除了,导致了这个问题。趁着这个机会,来总结一下Web中的事件系统。


••••   Web中的事件  ••••


事件并不是 JavaScript的核心部分,他们是在浏览器的 WebApi中定义的。下面列举的几种情况,都属于发生了事件。


  • 用户在某个元素上点击鼠标或悬停光标。
  • 用户在键盘中按下某个按键。
  • 用户调整浏览器的大小或者关闭浏览器窗口。
  • 一个网页停止加载。
  • 提交表单。
  • 播放、暂停、关闭视频。
  • 发生错误。

我们可以在代码中使用 事件处理器来处理各种事件。


••••   事件模型 ••••


假设我们有这么一段 html代码:

<html>
    <body>
        <table>
            <tbody>
                <tr>
                    <td>Shady Grove</td>
                    <td>Aeolain</td>
                </tr>
                <tr>
                    <td>Over the River, Charile</td>
                    <td>Dorian</td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

如果我们点击 over theRive,Charile,整个事件流程如下:

640.jpg



事件会经历三个阶段,上图中分别由红色、蓝色、绿色标出。第一阶段为红色,事件流从根元素一直走到点击的目标元素,这个过程称为 捕获。第二阶段为蓝色。这个阶段中,会处理点击事件,为事件加上各种属性等。第三阶段为绿色,事件又回重新回到根元素,这个过程称为 冒泡。在整个事件流中,我们在事件流经过的任何元素上,都能监听到该事件,从而进行处理。


一般建议在冒泡阶段处理事件,这样可以最大限度的兼容各种浏览器。


注意:blur、focus、load、unload 等几个事件不会冒泡。

原因是在于:这些事件仅发生于自身上,而它的任何父节点上的事件都不会产生,所有不会冒泡。

我们可以查看事件的bubbles属性,来判断该事件是否可以冒泡。


••••   事件处理  ••••


EventTarget


EventTarget是一个由可以接收事件的对象实现的接口,并且可以为它们创建侦听器。Web中的所有事件处理器都是由 EventTarget"提供"的。


640.jpg


addEventListener


该方法将指定的监听器注册到  EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素  Element, DocumentWindow或者任何其他支持事件的对象 (比如 XMLHttpRequest)。其标准语法如下:

1. target.addEventListener(type, listener[, options]);
2. target.addEventListener(type, listener[, useCapture]);
  • type: 字符串。表示事件类型,比如: click。

  • listener:函数。事件触发时的回调函数。这个函数会接受一个 Event事件对象。这个 Event事件对象中,包含了以下重要的属性和方法(这里只列举出常用的)


640.jpg

options :对象。指定一个 listener的配置参数。


640.jpg

  • useCapture:布尔值,可选。默认为 false,事件在冒泡过程中触发 listener


removeEventListener


删除使用 addEventListener注册到 target上的事件。标准语法:

target.removeEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, useCapture]);

为了提高页面性能,我们在处理完某事件,并且不用继续监听该事件时,可以将之前注册的事件监听函数移除。需要注意的是,如果注册事件时,在捕获或冒泡阶段均进行了监听,那么移除时需要分别移除。


currentTarget 与 target的区别


在事件处理函数中,我们经常会使用到事件的这两个属性。 currentTarget表示注册事监听的对象。 target表示事件起源的对象。举个例子:

1. <div id="father">
2.      <div id="child1">child1</div>
3.      <div id="child2">child2</div>
4.      <div id="child3">child3</div>
5. </div>
6. 
7. document.getElementById('father').addeventListener('click', function(e){
8.     console.log(e.currentTarget);
9.     console.log(e.target);
10. });

我们将事件处理函数绑定在 father上。现在,如果我们点击的是 child1,由于 child1是事件源,那么 e.target就是 child1。而我们的事件处理函数是绑定在 father上的,所以, e.currentTarget就是 father。这一点在开发过程中需要特别注意。

••••   事件代理 ••••


这个概念依赖于这样一个事实,如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每个子节点,而不是每个子节点单独设置事件监听器。举个栗子:

<ul>
    <li>1<li>
    <li>2<li>
    <li>3<li>
    <li>4<li>
    <li>5<li>
    <li>6<li>
    <li>7<li>
    <li>8<li>
    <li>9<li>
</ul>

我们要实现点击每一个 li的时候,输出 li内对应的数字,我们当然可以直接在所有的 li上分别绑定一个事件。但是这样会造成内存的浪费。我们可以只在 ul上绑定一个事件,根据事件的 target来获取当前点击的 li,拿到该 li内对应的数字。


document.querySelector('ul').addEventListener('click', function(e){
    if(e.target && e.target.nodeName === "LI") {
        console.log(e.target.innerHTML);
    }
});

••••   自定义事件  ••••


最新的DOM标准允许我们自定义事件。直接看下面的例子。

var fakeNode = document.createElement('Coy'); // 创建一个自定义元素
var evt = document.createEvent('Event'); // 创建一个自定义事件
var evtType = 'test'; // 自定义事件的类型
// 事件监听函数
fakeNode.addEventListener(evtType, function(e){ 
    console.log(e); // e.type === 'test';
}, false);
// 初始化事件。
// initEvent用法:event.initEvent(type, bubbles, cancelable);
evt.initEvent(evtType, false, false); 
// 向fakeNode派发evt事件
fakeNode.dispatchEvent(evt);


••••  写在后面  ••••


事件,是前端开发中的一个基础。虽然比较简单,但是十分重要。本文总结了web事件的一些知识点,符合预期

相关文章
|
前端开发 开发者 安全
JSF表单处理大揭秘:数据绑定与事件处理,如何让Web应用更加智能?
【8月更文挑战第31天】在现代Web应用开发中,JSF(JavaServer Faces)框架因强大的表单处理能力而广泛应用。其数据绑定机制可实现表单控件与后端模型的双向传输,降低前后端耦合度,提高代码维护性和类型安全性。事件处理机制则支持丰富的内置与自定义事件,进一步增强应用灵活性。本文通过示例代码展示这些特性,帮助开发者更好地利用JSF构建高效、灵活的Web应用。然而,JSF也存在组件库较小和学习成本较高等局限,需根据具体需求权衡使用。
129 0
|
前端开发 JavaScript 开发者
掌握Web前端事件处理精髓:从事件冒泡到事件委托,轻松优化你的交互体验与代码性能!
【8月更文挑战第23天】在Web前端开发中,事件处理是实现用户交互的关键机制。其中,事件冒泡与事件委托是优化页面性能、简化代码的重要手段。事件冒泡是指事件从触发它的元素开始,沿着DOM树向上逐层传播至根节点的过程。通过阻止事件冒泡,可以控制事件的影响范围。而事件委托则是利用事件冒泡特性,在父元素上设置监听器来响应子元素的事件,这种方法减少了监听器的设置数量,特别适用于动态添加的子元素,提高了代码的可维护性和性能。掌握这两种技术,能帮助开发者构建更高效、更简洁的应用程序。
226 0
|
JavaScript 前端开发 C++
【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
【5月更文挑战第2天】【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
|
JavaScript 前端开发 开发者
在Web开发中,事件处理是一个至关重要的概念
【5月更文挑战第17天】Vue.js的事件处理是其核心特性之一,允许开发者响应用户操作。通过v-on(或@)指令绑定DOM事件到方法,实现交互。事件修饰符如.stop、.prevent等简化处理逻辑。此外,Vue支持自定义事件,便于组件间通信,如子组件通过$emit触发事件,父组件使用v-on监听并响应。理解这些机制能帮助开发者更有效地管理Vue应用的事件流程。
118 0
|
存储 前端开发 JavaScript
【亮剑】在Web开发中,滚动事件(onScroll)是一个常见且强大的交互手段。
【4月更文挑战第30天】在React中,利用`onScroll`事件可实现无限滚动、动态加载和视差效果。通过`componentDidMount`和`componentWillUnmount`(类组件)或`useEffect`(函数组件)添加/移除滚动监听器。为了优化性能,需注意节流、防抖、虚拟滚动和避免同步计算。实战案例展示了如何结合Intersection Observer实现无限滚动列表,当最后一个帖子进入视口时加载更多数据。关注性能,确保应用流畅。
298 0
|
JavaScript 前端开发 API
「深入探究Web页面生命周期:DOMContentLoaded、load、beforeunload和unload事件」
在 Web 开发中,了解页面生命周期是非常重要的。页面生命周期定义了页面从加载到卸载的整个过程,包括各种事件和阶段。在本文中,我们将详细介绍四个关键事件:DOMContentLoaded、load、beforeunload 和 unload。我们将探讨这些事件的属性、API、应用场景,并提供一些代码示例和参考资料。
|
存储 JavaScript 前端开发
web前端面试高频考点——Vue3.x升级的重要功能(emits属性、生命周期、多事件、Fragment、移出.async、异步组件写法、移出 filter、Teleport、Suspense...)
web前端面试高频考点——Vue3.x升级的重要功能(emits属性、生命周期、多事件、Fragment、移出.async、异步组件写法、移出 filter、Teleport、Suspense...)
346 0
|
JavaScript 前端开发 UED
事件处理(Event Handling):构建交互性Web应用的基石
在现代Web应用开发中,交互性是吸引用户的重要因素之一。而事件处理是实现这种交互性的关键。通过响应用户的操作,您可以创造出令人愉悦的用户体验。在本博客中,我们将深入探讨事件处理的概念、不同类型的事件、事件绑定、事件冒泡以及如何有效地使用事件处理来构建交互性强大的Web应用。
379 0
|
缓存 JavaScript 前端开发
web前端面试高频考点——JavaScript-Web-API 篇(一)DOM、BOM、事件
web前端面试高频考点——JavaScript-Web-API 篇(一)DOM、BOM、事件
268 0