欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

拨开JS事件的迷雾(二)

程序员文章站 2022-03-31 14:52:02
...

上一篇文章,我们聊了什么是事件,以及多种绑定方法,这篇我们接着聊。

怎么实现

日常工作中,我们要做的东西通常都是来自某个想法,比如,按钮点击之后要怎样,划过要怎样,还有悬停、滚动、拖拽、手机屏幕转换等等,诸多场景。

但这些想法怎么实现呢?似乎有点无从下手,其实编程语言的设计者已经为我们考虑了这个问题,它为我们准备了很多可以和不同场景相匹配的工具,就好比厨房里的铲子、勺子、筷子、叉子、菜刀,按需取用即可,而且随着技术的演变,用户场景的丰富,它也会与时俱进,这就涉及到下面要讲的事件类型

事件类型

事件的种类可谓相当繁多,有可见的,有不可见的,大致可分为如下几类:

  • UI:load、select、resize、scroll等
  • 焦点:blur、focus、change等
  • 鼠标:click、mousedown/up、mouseenter/leave、clientX/clientY等
  • 键盘:keydown/up、keypress
  • 触摸:touchstart、touchend、touchmove等
  • 手势:gesturestart、gestureend、gesturechange等
  • 设备:orientationchange、deviceorientation等

上面这些,大都是人为操作,还有些事件是网页状态带来的,比如:网页加载完成、提交表单、网页出错等。

除此之外,还有变动事件,复合事件,HTML5新加入的一些事件,不再一一列出。

完整列表可在这里查看Web Events

网页上几乎每个动作都能够触发某个事件,网页代码也时刻准备响应这些事件,有时候它可能给我们带来麻烦,但多数时候是能够为我所用来解决问题的,这里没有多少难以理解的地方,就不再赘述。

事件冒泡/捕获

如果说事件当中有几大谜题,冒泡/捕获定能占据一席,按照最简单的逻辑,当满足了“元素、条件、执行内容”三者之后,事件应该就完整了,那冒泡和捕获又是什么意思?为什么会存在呢?

实际上,他们是描述事件触发时序问题的术语。

事件捕获指的是从总的父级到触发事件的那个节点,即自上而下地触发事件。相反的,事件冒泡是自下而上地触发事件。

用两个图来展示:

事件冒泡

事件捕获

如此说来,这两个过程看似浅显易懂,没那么难理解,可是它们为什么存在?

找了挺多资料,都只说它们是什么,怎么用,却没有说设计意图,不过还是看到一种可能合理的解释。

我们可以这样想,网页上的元素都是层层嵌套的,比如,一个body,套个div,再套个p,p里面再加个按钮,它们相当于若干个矩形进行叠放,那么,如果我点一下按钮所在的区域(注意,我强调了区域,即不先入为主地认为点的是按钮),那到底是点了谁呢?是按钮本身,还是包含它的p,或者是在点整个页面呢?

给不出准确答案吧?因为你的手指就在那里,你的想法,或者说,我想让你的点击起到什么效果,得有个设定的方法或者机制吧?之前就说了,用户的任何一种行为都会对应某种结果,那么,浏览器的开发者自然不会让这种模棱两可、无法确定的东西真的没法解决,于是就给出了两种事件流的形式,冒泡或者捕获,开发者可选择是否用、用哪个、怎么用,这就提供了较大的可控性和灵活性。

事件对象

JS领域有一句很有名的话——一切皆为对象,如果单看”对象“这个知识点,似乎一点都不难,每个人都能随口说出几种创建和使用对象的方法,但是,JS当中的很多对象都是很抽象的,不知怎地,它就存在那里了,事件对象便是其中之一。

先来看段代码:

function bgChange(e) {
var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
    e.target.style.backgroundColor = rndCol;
    console.log(e);
}  

btn.addEventListener('click', bgChange);
复制代码

不难看出,这段代码可通过点击某元素来改变其背景色,但有个莫名的小东西出现了,就是”e“,这里的e是什么?又能做些什么呢?

你一定见过它,或者,你见过跟它长得很像的event、evt,这是个固定的指定名称的参数,被称为“事件对象”,它被自动传递给事件处理函数,以提供额外的功能和信息

初看这种写法,我也很纳闷,有什么事不能明着来,非要暗里作怪?但人家就是这么设计的,我们只能尽量去理解。

那么,事件对象有什么用途呢,可多着嘞,你一定也见过,譬如:

  • 阻止默认行为 什么是默认行为?链接跳转、表单提交等都是,这样写就可以加以阻止: e.preventDefault();

  • 阻止事件冒泡 事件冒泡是一种事件的执行机制,有些时候会造成意向不到的结果,需要阻止,像这样: e.stopPropagation();

  • 事件委托 上面一个应用是阻止事件冒泡,但有些时候,它又能给我带来好处,正所谓凡事都有两面性。 事件委托的意思是,当一个父元素有很多子元素,每个子元素都将执行同样的事件,那么,没必要给它们重复绑定,只要将事件监听器设置其父元素之上即可,举例如下:

    <ul id="parent-list">
        <li id="post-1">Item 1</li>
        <li id="post-2">Item 2</li>
        <li id="post-3">Item 3</li>
        <li id="post-4">Item 4</li>
        <li id="post-5">Item 5</li>
        <li id="post-6">Item 6</li>
    </ul>
    // Get the element, add a click listener...
    document.getElementById("parent-list").addEventListener("click"function(e) {
        // e.target is the clicked element!
        // If it was a list item
        if(e.target && e.target.nodeName == "LI") {
            // List item found!  Output the ID!
            console.log("List item ", e.target.id.replace("post-"""), " was clicked!");
        }
    });
复制代码

这是个列表,事件监听器位于ul上,但最终选择执行的目标元素是li。

当然,事件对象不止这些作用,它还有很多属性可以操作,譬如:

  • event.target.nodeName   
  • event.target.id      
  • event.target.className  
  • event.target.innerHTML 等。

在此不再赘述,具体可自行试验和研究。

总结

在使用事件的过程中,除了知道用什么,怎么用,还需要注意它可能引起的内存与性能问题。譬如:

  • 要限制一个页面当中的事件处理程序数量,否则,数量过多会占用太多内存,造成反应不灵敏,建立在冒泡机制上的事件委托可以帮助减少处理程序的数量。
  • 在浏览器卸载页面之前最好移除页面中的事件处理程序。

事件的细节十分之多,两篇文章远远说不完,所以,这里只是概述,并未深入,但还是希望能对耐心读完的你有所帮助!

接下来还会逐个涉及JS领域的其他知识,欲知后事如何,我们下回继续。

参考链接:Events

转载于:https://juejin.im/post/5b9142e3f265da0a8a6a8639