javascript中的Event事件对象详解

ε祈祈猫儿з 提交于 2019-12-09 07:27:37

在JavaScript中对于事件来讲,首先,我们需要了解这样几个概念:事件;事件处理程序;事件类型;事件流;事件冒泡;事件捕获;事件对象;浏览器内核;事件绑定;事件方面的性能优化(事件委托、移除事件处理程序);常见的浏览器兼容问题等。

什么是事件event:
    JavaScript事件是:浏览器、文档(document)窗口中的发生的特定的交互瞬间;而JavaScript和HTML之间的交互行为就是通过事件来触发的。                    
            
事件处理程序:
    事件处理程序:我们用户在页面中进行的点击这个动作,鼠标移动的动作,网页页面加载完成的动作等,都可以称之为事件名称,
    即:click、mousemove、load等都是事件的名称。响应某个事件的函数则称为事件处理程序,或者叫做事件侦听器。            
            
            
事件类型:
    在JavaScript中事件大至分为了三大类,分别是一般事件、表单事件、页面事件这3种。

    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事件、设备事件(单点触控)、触摸事件touch、手势事件等各种事件等。            
    
    
事件流:
    浏览器层次顺序:document -> html -> body -> div父元素 -> input子元素】,document最上层祖先元素, input最下层后代元素。
                
    什么是事件流:事件流是描述从页面中接收事件的顺序【从内到外(冒泡),从外到内(捕获)】;
    IE与原来的NetScape(网景),对于事件流提出的是完全不同的顺序。IE团队提出的是事件冒泡流;NetScape的事件流是事件捕获流。
    简单的讲:当给一个DIV绑定一个点击事件,又在DIV里面放一个按扭并给按扭也绑定一个点击事件,此时你点击里面按扭的同时,外面DIV的点击事件也会被触发。
                
【事件冒泡】、JS阻止事件冒泡方法:event.stopPropagation(),JS阻止默认行为方法:event.preventDefault() 注:这两个方法属于event的
    所谓事件冒泡 就是事件最开始从最具体的元素(文档中嵌套层次最深的那个点【当前绑定事件的那个元素】)接收,然后逐级向上传播至最不具体的那个节点(document节点,即最上层的节点)。
            
【事件捕获】、和事件冒泡刚好【相反】,它是事件从最不具体的节点(document)先接收到事件,然后再向下逐一捕获至(文档中嵌套层次最深的那个点【当前绑定事件的那个元素】)。    
    简单地说,事件冒泡和事件捕获都是一种事件传递的机制。这种机制可以使事件在不同级
    的元素间传递。事件冒泡是从事件触发的源节点,向父节点传递,直到到达最顶节点。而事件
    捕获则是从最顶节点,逐步向下传递,直到到达事件触发的源节点。
    
    在一些标准的浏览器中,如IE9以上,Chrome 、Firefox 、Safari浏览器等,支持这两种冒泡方式。而事实上,
    准确的说,是这两种方式的混合方式。因为W3C采取的就是这两种方式的结合:先从顶级节点
    开始,将事件向下传递至源节点,再从源节点冒泡至顶节点。
    
    而在IE及Opera(以下说的都是老版本的欧朋,新版本的欧朋经检测是支持事件捕获的)
    下,是不支持事件捕获的。而这个特点最明显体现在事件绑定函数上。IE、Opera的事件
    绑定函数是attachEvent,而Chrome等浏览器则是addEventListener,
    
    而后者比前者的参数多了一个——这个参数是一个布尔值,这个布尔值由用户决定,用户若设为true,
    则该绑定事件以事件捕获的形式参与,若为false则以事件冒泡的形势参与。
    而这个参数在IE和Opera浏览器中是不存在的——根本原因是它们不支持事件捕获。    
                    
            
事件对象:
    事件对象:在触发DOM上的某个事件的时候,会产生一个事件对象event,而在这个对象当中会包含着所有与事件有关的信息。
    
事件对象其中有两个信息,我们最为常用,分别是type和target:

    type表示的是被触发事件的类型;
    target表示的是事件的目标。

其他:        
    bubbles:表示事件是否冒泡
    cancelable:表示是否可以取消事件的默认行为
    currentTarget:表示事件处理程序当前正在处理事件的那个元素
    defaultPrevented:表示是否调用了preventDefault()
    detail:表示的是与事件相关的细节信息
    eventPhase:调用事件处理处理程序的阶段:1表示捕获阶段、2表示处于目标、3表示冒泡阶段            
            
            
浏览器内核:
    1、Trident:(IE内核) Trident内核的常见浏览器有:
    IE6、IE7、IE8(Trident 4.0)、IE9(Trident 5.0)、IE10(Trident 6.0);
    360安全浏览器(1.0-5.0为Trident,6.0为Trident+Webkit,7.0为Trident+Blink)猎豹极轻浏览器,360极速浏览器(7.5之前为Trident+Webkit,7.5为Trident+Blink)
    猎豹安全浏览器(1.0-4.2版本为Trident+Webkit,4.3及以后版本为Trident+Blink)猎豹极轻浏览器,
    傲游浏览器(傲游1.x、2.x为IE内核,3.x为IE与Webkit双核)、百度浏览器(早期版本)世界之窗浏览器
    最初为IE内核,2013年采用Chrome+IE内核)、2345浏览器、腾讯TT、淘宝浏览器、采编读浏览器、搜狗高速浏览器(1.x为Trident,2.0及以后版本为Trident+Webkit)、阿云浏览器(早期版本)、
    瑞星安全浏览器、Slim Browser、 GreenBrowser、爱帆浏览器(12 之前版本)、115浏览器、155浏览器、闪游浏览器、N氧化碳浏览器、糖果浏览器、彩虹浏览器、瑞影浏览器、
    勇者无疆浏览器、114浏览器、蚂蚁浏览器、飞腾浏览器、速达浏览器、佐罗浏览器、海豚浏览器(iPhone/iPad/Android)、UC浏览器(Blink内核+Trident内核)等。
                    
    2、Gecko:(Firefox内核) Netscape6开始采用的内核,后来的Mozilla FireFox(火狐浏览器) 也采用了该内核,Gecko的特点是代码完全公开。
    
    3、Presto:(Opera前内核) (已废弃) Opera现已改用Google Chrome的Blink内核。
    
    4、Webkit:(Safari内核,Chrome内核原型,开源):它是苹果公司自己的内核,也是苹果的Safari浏览器使用的内核 【是现在大部份移动端:Android安桌,apple苹果采用的内核】。            
                    
            
            
            
JvaScript事件的三种绑定方式【事件处理程序】:
            
            
事件绑定方式一【HTML事件处理程序】:就是将事件直接内嵌内HTML结构标签元素内的 【不推荐用,因为不灵活】 
                            
例:
    <input type="button" οnclick="alert("我是事件绑定方式一:HTML事件处理程序,我是内嵌在HTML结构中的");" value="事件绑定方式一【内嵌】" />

或    <input type="button" οnclick="mupiaoFn()" value="事件绑定方式一【调用】" />
                
    /*------事件绑定方式一:HTML事件处理程序------*/
    function mupiaoFn(){
        alert("我是事件绑定方式一:HTML事件处理程序");
    }
            
                    
            
事件绑定方式二【DOM 0级事件处理程序】:就是把一个函数/方法赋给一个事件处理程的 属性如:id 、class 、元素名等 【用得最多,兼容性好,简单,灵活,跨浏览器 ;缺点:不能绑定多个同类型事件】
                
例:
    <input type="button" name="eventBtn2" id="eventBtn2" value="事件绑定方式二【通用属性绑定】" />
                
    /*------事件绑定方式二:DOM 0级事件处理程序------*/
    var Btn2 = document.getElementById("eventBtn2");//给谁绑定事件,就要先获取谁
                
    //绑定事件1:【赋给方式】
    Btn2.onclick = function(){
        alert("我是事件绑定方式二:DOM 0级事件处理程序");
    }
            

    //绑定事件2:【调用方式】
    function publick(){
        alert("我也是事件绑定方式二:DOM 0级事件处理程序");
    }
    Btn2.onclick = publick; //注:publick后面不要加()括号,否则会变为立即执行函数!
            
    //删除事件:
    Btn2.onclick = null;    注:
        在DOM0级事件处理程序推出之后,被广为使用,可是出现了这样一个问题,当我们希望给同一个元素/标签绑定多个同类型事件的时候(如,为上面的按扭标签绑定2个或是个以上的点击事件),是不被允许的。
        
        那么,此时,出现了另一种事件处理程序,就是DOM2级的事件处理程序,【注:没有DOM1级事件这个概念哦】在DOM2级当中,定义了两个基本方法,
        
        用于处理指定(即绑定)和删除事件处理程序的操作,分别是addEventListener()和removeEventListener(),IE9+、FireFox、Safari、Chrome和Opera都是支持DOM2级事件处理程序的。
        
        对于IE8-,则使用的是IE专有的事件处理程序:两个类似的方法——attachEvent()与detachEvent()。    
            
            
事件绑定方式三【DOM 2级事件处理程序 / 监听事件】:addEventListener()和removeEventListener()监听事件接收3个参数:事件类型(注:不要加 on), 处理函数 , false:冒泡/true:捕获
                                            IE中:attachEvent()和detachEvent()监听事件接收2个参数:事件类型(注:要加 on), 处理函数//只支持冒泡                

例:
    <input type="button" name="eventBtn3" id="eventBtn3" value="事件绑定方式三" />
                
    /*------事件绑定方式三【DOM 2级事件处理程序 / 监听事件】------*/
                
    var Btn3 = document.getElementById("eventBtn3");//给谁绑定事件,就要先获取谁
        
    //添加监听事件1:【内嵌方式】
    Btn3.addEventListener('click' , function(){
        alert("我是事件绑定方式二:DOM 2级事件处理程序");
    } , false) //false:冒泡,true:捕获
                
    //添加监听事件2:【调用方式】
    Btn3.addEventListener('click' , addevFn , false);
    function addevFn(){    
        alert("我是事件绑定方式二:DOM 2级事件处理程序 【调用方式】");
    }
                
    //添加不同的监听事件:鼠标移入事件【调用方式】
    Btn3.addEventListener('mouseover' , addevFn2 , false);
    function addevFn2(){
        alert(this.value);
    }
                
    //*删除监听事件【注:删除时事件类型名、事件函数名要一一对应哦(就是和添加事件时的参数一样)】
    Btn3.removeEventListener("mouseover" , addevFn2, false)
                
                
    //IE8及以下的添加和删除监听事件方法:(注:IE9及以上的就用上面的方法啦)            
                
    //IE8及以下的添加监听事件1:【内嵌方式】 (注 attachEvent 和 detachEvent方法只传两个参数,前面两个和上面一样,而第3个参数是因为在IE中默认就是冒泡方式,所以不用传第3个参数啦)
    Btn3.attachEvent("onclick" , function(){
        alert("我是IE8及以下的添加监听事件方法,【内嵌方式】");
    });
                
    //IE8及以下的添加监听事件2:【调用方式】(注:attachEvent 和 detachEvent 事件类型前而一定要加  on 才可以哦)
    Btn3.attachEvent("onclick" , addevFn3);
    function addevFn3(){
        alert("我是IE8及以下的添加监听事件方法,【调用方式】");
    }
                
    //IE8及以下的删除监听事件
    Btn3.detachEvent("onclick" , addevFn3);                
            
            
事件方面性能优化:事件委托和事件处理程序的移除

    在JavaScript代码当中,添加到页面中的事件越多,页面的性能也就越差。导致这一问题的原因主要有:
                
    每个函数都是对象,都会占用内存。内存中对象越多,性能也就越差。
    必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。
    为了进行页面的性能优化,因此我们会采用两种方法,就是上面提到的——事件委托和事件处理程序的移除。
                
事件委托:
                
    什么时候使用事件委托,其实,简单来说,当时一个页面事件处理程序比较多的时候,我们通常情况下会使用它。
                
    事件委托主要利用了事件冒泡,只指定一个事件处理程序,就可以管理一个类型的所有事件。例如:我们为整个一个页面制定一个onclick事件处理程序,
    此时我们不必为页面中每个可点击的元素单独设置事件处理程序
                
        事件委托:给元素的父级或者祖级,甚至页面绑定事件,然后利用事件冒泡的基本原理,通过事件目标对象进行检测,然后执行相关操作。其优势在于:

    大大减少了事件处理程序的数量,在页面中设置事件处理程序的时间就更少了(DOM引用减少——也就是上面我们通过id去获取标签,所需要的查找操作以及DOM引用也就更少了)。
    document(注:上面的例子没有绑定在document上,而是绑定到了父级的div上,最为推荐的是绑定在document上)对象可以很快的访问到,而且可以在页面生命周期的任何时点上为它添加事件处理程序,
    并不需要等待DOMContentLoaded或者load事件。换句话说,只要可单击的元素在页面中呈现出来了,那么它就立刻具备了相应的功能。
    整个页面占用的内存空间会更少,从而提升了整体的性能。

移除事件处理程序
                
    每当将一个事件处理程序指定给一个元素时,在运行中的浏览器代码与支持页面交互的JavaScript代码之间就会建立一个连接。连接数量也直接影响着页面的执行速度。
    所以,当内存中存在着过时的“空事件处理程序”的时候,就会造成Web应用程序的内存和性能问题。
                
那么什么时候会造成“空事件处理程序”的出现呢?
                
    文档中元素存在事件,通过一些DOM节点操作(removeChild、replaceChild等方法),移除了这个元素,但是DOM节点的事件没有被移除。
    innerHTML去替换页面中的某一部分,页面中原来的部分存在事件,没有移除。
    页面卸载引起的事件处理程序在内存中的滞留。
                
解决方法:
                
    合理利用事件委托;
    在执行相关操作的时候,先移除掉事件,再移除DOM节点;
    在页面卸载之前,先通过onunload事件移除掉所有事件处理程序。
 

转载于:https://my.oschina.net/lovemiao/blog/3035671

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!