`
草原雪花
  • 浏览: 10588 次
社区版块
存档分类
最新评论

js事件

阅读更多

JavaScript事件 详细讲解

(转载的,非原创)

 


前言:原本这篇文章是打算6号书写出来的,但是基于某些私人原因,希望能够通过这篇文章尽可能的将事件讲解的更加详细和通俗易懂,因此,多花了一天时间,不多说了,接下来对“事件”来一个较为详细的介绍。
欢迎大家互相学习交流。独行冰海
需要了解事件的什么?
对于事件来讲,首先,我们需要了解这样几个概念:事件;事件处理程序;事件类型;事件流;事件冒泡;事件捕获;事件对象;事件方面的性能优化(事件委托、移除事件处理程序);常见的浏览器兼容问题。
事件的概念
事件:指的是文档或者浏览器窗口中发生的一些特定交互瞬间。我们可以通过侦听器(或者处理程序)来预定事件,以便事件发生的时候执行相应的代码。
事件处理程序
事件处理程序:我们用户在页面中进行的点击这个动作,鼠标移动的动作,网页页面加载完成的动作等,都可以称之为事件名称,即:click、mousemove、load等都是事件的名称。响应某个事件的函数则称为事件处理程序,或者叫做事件侦听器。
接下来我们用一段代码来再说明一下上面这两个抽象的概念,具体解释见代码注释:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <div id="main">理解事件的基本概念</div>
</body>
<script>
    var main = document.getElementById('main');
    // 此处click,点击,是一种事件的名称,是浏览器窗口中发生点击的瞬间。on这个单词,其实就是让click这个事件得以相应,因此,onclick就叫做事件处理程序。下面这段代码,我们通过处理程序(onclick)为main这个元素预定了点击(click),这样在点击(click)发生的时候,执行函数中的代码(弹出一个对话框)。
    main.onclick = function(){
        alert('点击了此处哦!');
    }
</script>
</html>
关于事件处理程序,从最初的发展到现在,经历了几次的变化。
事件处理程序的名字是以“on”开头,因此click事件的处理程序就是onclick。在最初,是使用HTML事件处理程序的,也就是说,某个元素(如div),支持的每一种事件,都可以使用一个与相应事件处理程序同名的HTML特性来制定(也就是标签的一个属性),这个特性的值就是能够执行的JavaScript代码。例如:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <p onclick="alert('click')">HTML事件处理程序</p>
</body>
</html>
当然,我们也可以再onclick=””当中进行函数的调用。
但是,无论哪种方法,都暴露出来HTML事件处理程序的很多问题:
首先,HTML代码域JavaScript代码紧密的耦合在一起,没有实现相互分离,在进行代码的更新与维护的时候就显得异常困难。
第二,扩展事件处理程序的作用域链在不同浏览器当中会导致不同的结果。
第三,如果不采用调用函数的方式,而是像例子中那样直接书写代码,那么代码的通用性很差,会使得整站的代码量很大,通用性差。如果提取出来,存放在函数当中,那么,会面临另一个问题——当函数还没有被定义,只是HTML、CSS代码加载完毕,用户进行点击,会完全没有反应。

基于上面的这些问题,人们逐渐的去完善了事件处理程序,此时出现了DOM0级事件处理程序。(第四代WEB浏览器中出现)
DOM0级事件处理程序是什么样子的呢?其实它就是我们平时最为常用的事件绑定,如下面这个例子:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <p id='btn'>DOM0级事件处理程序</p>
</body>
<script>
    var btn = document.getElementById('btn');
    btn.onclick = function(){
        alert(this.innerHTML);
    }
</script>
</html>
在DOM0级事件处理程序推出之后,广为各个用户的使用,但是,却出现了这样一个问题,当我希望为同一个元素/标签绑定多个同类型事件的时候(如,为上面的这个p标签绑定3个点击事件),是不被允许的。那么,此时,出现了另一种事件处理程序,就是DOM2级的事件处理程序,在DOM2级当中,定义了两个基本方法,用于处理指定(即绑定)和删除事件处理程序的操作,分别是addEventListener()和removeEventListener(),IE9+、FireFox、Safari、Chrome和Opera都是支持DOM2级事件处理程序的。对于IE8-,则使用的是IE专有的事件处理程序:两个类似的方法——attachEvent()与detachEvent()。
具体实例代码如下:(以addEventListener为例,给出了两种书写方式)
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <p id='btn'>DOM0级事件处理程序</p>
</body>
<script>
    var btn = document.getElementById('btn');
    btn.addEventListener("click", test, false);
    function test(){
        alert(this.innerHTML);
    }
</script>
</html>
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <p id='btn'>DOM0级事件处理程序</p>
</body>
<script>
    var btn = document.getElementById('btn');
    btn.addEventListener("click", function(){
        alert(this.innerHTML);       
    }, false);
</script>
</html>
addEventListener()和removeEventListener()中的第三个参数,表示的是在哪个事件阶段进行事件处理,如果是false,则指的是冒泡阶段;如果是true,则指的是捕获阶段。
在事件方面,IE与FF存在着一系列的兼容问题,具体问题可查看博文《IE浏览器与FF火狐浏览器在事件上的兼容问题》
关于如何创建一个兼容全部浏览器的事件侦听器,我们在下一篇博文《跨浏览器的事件处理函数——处理DOM2级事件兼容 》当中再做详细的介绍和代码示范。
事件类型
之前在课程的讲解当中,我们把事件分为了三大类,分别是一般事件、表单事件和页面事件。当前我们可以再做细分:
UI事件:如load、unload、error、resize、scroll、select、DOMActive,是用户与页面上的元素交互时触发的。
焦点事件:如blur、DOMFocusIn、DOMFocusOut、focus、focusin、focusout,在元素获得或失去焦点的时候触发,这些事件当中,最为重要的是blur和focus,有一点需要引起注意,这一类事件不会发生冒泡!
鼠标与滚轮事件:如click、dblclick、mousedown、mouseenter、mouseleave、mousemove、mouseout、mouseover、mouseup,是当用户通过鼠标在页面执行操作时所触发的。
滚轮事件:mousewheel(IE6+均支持)、DOMMouseScroll(FF支持的,与mousewheel效果一样)。是使用鼠标滚轮时触发的。
文本事件:textInput,在文档中输入文本触发。
键盘事件:keydown、keyup、keypress,当用户通过键盘在页面中执行操作时触发。
合成事件:DOM3级新增,用于处理IME的输入序列。所谓IME,指的是输入法编辑器,可以让用户输入在物理键盘上找不到的字符。compositionstart、compositionupdate、compositionend三种事件。
变动事件:DOMsubtreeModified、DOMNodeInserted、DOMNodeRemoved、DOMAttrModified、DOMCharacterDataModified等,当底层DOM结构发生变化时触发。IE8-不支持。
变动名称事件:指的是当元素或者属性名变动时触发,当前已经弃用!
对于事件的基本类型,随着HTML5的出现和发展,又新增了HTML5事件、设备事件、触摸事件、手势事件等各种事件,在后面我们再详细介绍。
事件流
事件流:描述的是从页面中接收事件的顺序。
IE与原来的NetScape(网景),对于事件流提出的是完全不同的顺序。IE团队提出的是事件冒泡流;NetScape的事件流是事件捕获流。
事件冒泡
事件冒泡:表示的是,事件开始的时候由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
事件捕获
事件捕获:表示的是,事件开始的时候由最不具体的节点接收,然后逐级向下传播到最具体的节点。
来看一个实例:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <div id="main">
        <p>理解事件的基本概念</p>
    </div>
</body>
</html>
如果单击了p标签,那么,如果是事件冒泡流的事件流机制,则click事件将按照如下顺序进行执行:p —— div —— body —— html —— document。
如果采用捕获流的事件流机制,则click事件的执行顺序为:document —— html —— body —— div —— p
对于冒泡流的事件流机制,存在如下的兼容问题:
<=IE5.5     p -> div -> body -> document
>=IE6.0        p -> div -> body -> html -> document
>=Mozilla 1.0    p -> div -> body -> html -> document -> window
欢迎大家互相学习交流。独行冰海
事件对象
事件对象:在触发DOM上的某个事件的时候,会产生一个事件对象event,而在这个对象当中会包含着所有与事件有关的信息。我们书写如下基本代码:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
</head>
<body>
    <div id="main">理解事件的基本概念</div>
</body>
<script>
    var main = document.getElementById('main');
    main.onclick = function(event){
        console.log(event);
    }
</script>
</html>
使用console.log打印出的结果如下图。
JavaScript事件 详细讲解 - 独行冰海 - 独行冰海

其中有两个信息,我们最为常用,分别是type和target。
type表示的是被触发事件的类型;
target表示的是事件的目标。
其他信息,如:
bubbles:表示事件是否冒泡
cancelable:表示是否可以取消事件的默认行为
currentTarget:表示事件处理程序当前正在处理事件的那个元素
defaultPrevented:表示是否调用了preventDefault()
detail:表示的是与事件相关的细节信息
eventPhase:调用事件处理处理程序的阶段:1表示捕获阶段、2表示处于目标、3表示冒泡阶段
在其中还有一些其他信息,在此就不再一一列举了。
事件方面性能优化
谈一谈事件方面如何优化性能——事件委托和事件处理程序的移除
在JavaScript代码当中,添加到页面中的事件越多,页面的性能也就越差。导致这一问题的原因主要有:
每个函数都是对象,都会占用内存。内存中对象越多,性能也就越差。
必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。
为了进行页面的性能优化,因此我们会采用两种方法,就是上面提到的——事件委托和事件处理程序的移除。
事件委托
很多人问我,什么时候使用事件委托,其实,简单来说,当时一个页面事件处理程序比较多的时候,我们通常情况下会使用它。
事件委托主要利用了事件冒泡,只指定一个事件处理程序,就可以管理一个类型的所有事件。例如:我们为整个一个页面制定一个onclick事件处理程序,此时我们不必为页面中每个可点击的元素单独设置事件处理程序(onclick)。还是,看一个例子。
效果:点击不同的元素执行不同的操作。
不使用事件委托:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
    <style>
        *{margin: 0;padding: 0;}
        .control span{
            float: left;
            width: 50px;
            height: 50px;
            line-height: 50px;
            font-size: 32px;
            text-align: center;
            border: 1px solid #f00;
        }
    </style>
</head>
<body>
    <div class='control'>
        <span id='left'>左</span>
        <span id='first'>1</span>
        <span id='second'>2</span>
        <span id='third'>3</span>
        <span id='right'>右</span>
    </div>
</body>
<script>
    var left = document.getElementById('left');
    var first = document.getElementById('first');
    var second = document.getElementById('second');
    var third = document.getElementById('third');
    var right = document.getElementById('right');
    left.addEventListener("click", function(){
        alert('点击的是左这个字,执行相关操作');       
    }, false);
    first.addEventListener("click", function(){
        alert('要执行第一个序号对应的相关操作');       
    }, false);
    second.addEventListener("click", function(){
        alert('要执行第二个序号对应的相关操作');       
    }, false);
    third.addEventListener("click", function(){
        alert('要执行第三个序号对应的相关操作');       
    }, false);
    right.addEventListener("click", function(){
        alert('点击的是右这个字,执行相关操作');       
    }, false);
</script>
</html>
不难看出,我们使用了5个事件侦听器,每设置一个就需要绑定一个。
使用事件委托:
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件-独行冰海</title>
    <style>
        *{margin: 0;padding: 0;}
        .control span{
            float: left;
            width: 50px;
            height: 50px;
            line-height: 50px;
            font-size: 32px;
            text-align: center;
            border: 1px solid #f00;
        }
    </style>
</head>
<body>
    <div class='control' id='control'>
        <span id='left'>左</span>
        <span id='first'>1</span>
        <span id='second'>2</span>
        <span id='third'>3</span>
        <span id='right'>右</span>
    </div>
</body>
<script>
    var control = document.getElementById('control');
    control.addEventListener("click", function(e){
        // 注意,此处没有考虑IE8-的浏览器,如果想书写兼容全部浏览器的事件处理程序,请查看下一篇博文
        var target = e.target;
        // 在此使用的是switch语句,也可以采用if进行判断
        switch(target.id){
            case "left" : {
                alert('点击的是左这个字,执行相关操作');
                break;
            }
            case "first" : {
                alert('要执行第一个序号对应的相关操作');
                break;
            }
            case "second" : {
                alert('要执行第二个序号对应的相关操作');
                break;
            }
            case "third" : {
                alert('要执行第三个序号对应的相关操作');
                break;
            }
           
            case "right" : {
                alert('点击的是右这个字,执行相关操作');
                break;
            }
        }
    }, false);
</script>
</html>
简要的总结一下所谓的事件委托:给元素的父级或者祖级,甚至页面绑定事件,然后利用事件冒泡的基本原理,通过事件目标对象进行检测,然后执行相关操作。其优势在于:
大大减少了事件处理程序的数量,在页面中设置事件处理程序的时间就更少了(DOM引用减少——也就是上面我们通过id去获取标签,所需要的查找操作以及DOM引用也就更少了)。
document(注:上面的例子没有绑定在document上,而是绑定到了父级的div上,最为推荐的是绑定在document上)对象可以很快的访问到,而且可以在页面生命周期的任何时点上为它添加事件处理程序,并不需要等待DOMContentLoaded或者load事件。换句话说,只要可单击的元素在页面中呈现出来了,那么它就立刻具备了相应的功能。
整个页面占用的内存空间会更少,从而提升了整体的性能。
移除事件处理程序
每当将一个事件处理程序指定给一个元素时,在运行中的浏览器代码与支持页面交互的JavaScript代码之间就会建立一个连接。连接数量也直接影响着页面的执行速度。所以,当内存中存在着过时的“空事件处理程序”的时候,就会造成Web应用程序的内存和性能问题。
那么什么时候会造成“空事件处理程序”的出现呢?
文档中元素存在事件,通过一些DOM节点操作(removeChild、replaceChild等方法),移除了这个元素,但是DOM节点的事件没有被移除。
innerHTML去替换页面中的某一部分,页面中原来的部分存在事件,没有移除。
页面卸载引起的事件处理程序在内存中的滞留。
解决方法:
合理利用事件委托;
在执行相关操作的时候,先移除掉事件,再移除DOM节点;
在页面卸载之前,先通过onunload事件移除掉所有事件处理程序。
关于事件的讲解就到此了,感谢各位的支持!
欢迎大家互相学习交流。独行冰海

 

分享到:
评论

相关推荐

    使用JavaScript事件综合查询,js事件大全

    JavaScript事件是浏览器或Node.js环境中发生的特定行为,如用户点击按钮、页面加载完成或输入框获得焦点等。事件驱动编程是JavaScript的核心特性之一,通过监听和处理这些事件,我们可以创建响应式的用户体验。 二...

    EventDispatcher,js事件派发器,javascript事件派发器

    在标题提到的"EventDispatcher, js事件派发器, javascript事件派发器"中,我们可以理解这是一个JavaScript实现的事件派发器,可能是作者的原创工作。用户可以通过GitHub上的问题跟踪系统(Issue)报告任何发现的错误...

    事件集合js事件集合js事件集合

    JavaScript(简称JS)...总的来说,JavaScript事件集合是构建动态和交互式网页的核心工具。通过深入理解和熟练应用事件监听、事件处理、事件冒泡、事件捕获等概念,开发者能够创建出更加丰富、响应迅速的Web应用程序。

    JavaScript程序设计——事件处理实验报告.docx

    实验报告详细介绍了JavaScript事件处理的相关知识,这在Web开发中是非常关键的一部分,因为事件是用户与网页交互的主要方式。以下是对各个知识点的详细说明: 1. **JavaScript事件基本概念**: - **事件**:是用户...

    JavaScript事件机制详细研究

    JavaScript 事件机制详细研究 JavaScript 事件机制是指浏览器中发生的各种事件,例如点击、鼠标悬停、键盘输入等,JavaScript 通过捕捉这些事件来执行相应的操作。本文将详细介绍 JavaScript 事件机制的实现方式和...

    js事件触发大全

    JS事件触发大全是指在 JavaScript 中各种事件的触发机制,这些事件可以在不同的元素上触发,例如按钮、链接、文本框、图片等。这些事件可以被 JavaScript 代码捕捉和处理,以便执行特定的操作。 事件类型 1. 鼠标...

    js 事件大全带简要注释

    Js事件大全 1.一般事件... 2 2.页面相关事件... 2 3.表单相关事件... 3 4.滚动字幕事件... 3 5.编辑事件... 3 6.数据绑定... 4

    javascript事件思维导图

    全面,直观javascript的事件

    JS针对浏览器窗口关闭事件的监听方法集锦

    在JavaScript中,监听浏览器窗口关闭事件对于实现特定的用户交互或数据保存功能至关重要。下面将详细介绍几种常用的浏览器关闭事件监听方法。 1. 方式一:适用于IE浏览器,仅在关闭时提示 ```javascript window....

    如何给javascript js事件传递参数.zip_jsp js

    如何给javascript js事件传递参数.zip

    10-JS事件基础.pptx

    在这个"10-JS事件基础"的教程中,我们将深入理解JavaScript中的事件处理机制,包括事件对象、事件冒泡、DOM事件流以及鼠标和键盘事件。 首先,让我们了解一下什么是事件对象。在JavaScript中,每当发生一个事件(如...

    javascript 事件

    JavaScript事件是Web开发中不可或缺的一部分,它允许用户与网页进行交互并响应用户的操作。...在阅读`event.js`这个文件和相关的博客文章后,你将能够深入理解JavaScript事件系统,并将其应用到自己的项目中。

    js 事件code 对应表

    JavaScript事件code对应表是JavaScript编程中非常重要的一个概念,它涉及到浏览器如何处理用户与网页的交互。在网页中,无论是点击按钮、滚动页面还是按下键盘上的键,都会触发各种事件。事件code就是用来识别这些...

    js右键菜单主要讲的JS事件流 一定要收藏哦

    通过自定义右键菜单,我们可以提升网页的用户体验,同时这也是一个很好的实践JavaScript事件处理和DOM操作的机会。记得在实际应用中考虑兼容性问题,确保你的代码能在不同的浏览器和设备上正常工作。

    JavaScript事件学习小结(五)js中事件类型之鼠标事件

    JavaScript事件学习小结(五)js中事件类型之鼠标事件 //www.jb51.net/article/86259.htm JavaScript事件学习小结(一)事件流 //www.jb51.net/article/86261.htm javaScript事件学习小结(四)event的公共成员...

    jem.js:Javascript 事件管理器

    jem.js(Javascript 事件管理器) 这是一个 Javascipt 库,可帮助我们编写事件驱动的 Javascript 代码。 没有依赖项,没有 jQuery,没有其他库。 这与 DOM 无关。 jem.js 用于您的自定义事件。 欢迎任何形式的...

    eventdispatcher.js, 自定义对象的JavaScript事件.zip

    eventdispatcher.js, 自定义对象的JavaScript事件 eventdispatcher.js 自定义对象的JavaScript事件用法[removed][removed][removed]

    JS事件OPTION事件触发

    JAVASCRIPT 实现OPTION的事件触发

    js事件监听机制(事件捕获)总结

    JavaScript事件监听机制是前端开发中不可或缺的一部分,它用于处理页面元素的各种交互,如点击、鼠标移动等。在本文中,我们将深入探讨事件监听,特别是事件捕获这一概念,以及如何在不同的浏览器环境中实现兼容。 ...

    svg加snap.svg.js能做出饼状图,柱状图,折线图,svg事件和js事件的结合,svg坐标

    SVG事件和JavaScript事件的结合使得交互式图形成为可能。例如,你可以为SVG元素添加点击事件监听器,当用户点击某个图形时触发特定的JavaScript函数。这可以用于显示详细信息、导航或执行其他操作。SVG事件包括`...

Global site tag (gtag.js) - Google Analytics