zoukankan      html  css  js  c++  java
  • 说说JavaScript中的事件模型

    1.javascript中为元素添加事件处理程序的方法
    有以下几种方式,可以为javascript元素添加事件处理程序

    (1) 直接将事件处理代码写在html中
    (2) 定义一个函数,赋值给html元素的onXXX属性
    (3) 使用element.onXXX方式
    以上三种方式,请看下面代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk"    />
    <title>添加事件的方法</title>
    <style>
         div {border:1px  solid blue;margin:10px;}
         div#divGrandpa {padding:10px;background-color:#aaaaaa;}
         div#divFather {padding:10px;background-color:#bbbbbb;}
         div#divSon {padding:10px;background-color:#cccccc;}
    </style>
    
    
    
    </head>
     <body>
    <div id="divGrandpa" style="500px;height:20px;" onclick="alert('直接将事件处理代码写在html中');">(1) 直接将事件处理代码写在html中 </div>
    
    <div id="divFather" style="500px;height:20px;" onclick="clk()" >(2) 定义一个函数,赋值给html元素的onXXX属性 </div>
    
    <div id="divSon" style="500px;height:20px;" >(3) 使用element.onXXX方式 </div>
    
    </div>
    
    </body>
    <script>
     function clk()
     {
      alert('定义一个函数,赋值给html元素的onXXX属性'); 
     }
     
     function clk1()
     {
      alert('使用element.onXXX方式'); 
     }
     
     var clkEle = document.getElementById('divSon'); 
     //这种方式,必须将本行代码放到上面的html代码<div id="divSon" ...>后面,
     //否则导致找不到divSon,返回null
     clkEle.onclick = clk1;
    </script>
    </html>

    (4) 使用addEventListener或attachEvent

    这是目前推荐的方式,较前两种方式功能更为强大,可以为元素添加多个事件handler,
    支持事件冒泡或捕获,前三种方式默认都是冒泡。
    IE6/7/8仍然没有遵循标准而使用了自己专有的attachEvent,且不支持事件捕获。
    注意attachEvent的第一个参数需要加上个"on",比如click事件时,传递参数需要是on+click=onclick
    addEventListener第三个参数为false表示事件冒泡,true
    attachEvent没有第三个参数,默认就是冒泡,没有捕获。
    这种方式代码如下:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk"    />
    <title>浏览器事件机制——冒泡处理</title>
    <style>
         div {border:1px  solid blue;}
         div#divGrandpa {padding:40px;background-color:#f00;}
         div#divFather {padding:40px;background-color:#0f0;}
         div#divSon {padding:40px;background-color:#00f;}
    </style>
    </head>
     <body>
    <div id="divGrandpa" style="300px;height:200px;" > I am Grandpa
           <div id="divFather" style="200px;height:120px;" > I am father
                <div id="divSon" style="100px;height:40px;" >
                    点击我 I am son
                </div>
           </div>
    </div>
    <script>
        function showSon() 
        {
            alert("I am son");
        }
        
        function showFather() 
        {
            alert("I am father");
        }
        
        function showGrandpa() 
        {
            alert("I am Grandpa");
        }
        
        var grandpa = document.getElementById("divGrandpa");
        var father = document.getElementById("divFather");
        var son = document.getElementById("divSon");
        
        if(window.addEventListener)
        {
            grandpa.addEventListener("click", showGrandpa, true);
            father.addEventListener("click", showFather, true);
            son.addEventListener("click", showSon, true);
        }
        else if (window.attachEvent)
        {
            grandpa.attachEvent("onclick", showGrandpa);
            father.attachEvent("onclick", showFather);
            son.attachEvent("onclick", showSon);
        }
    </script>    
    </body>
    </html>

    2. 事件模型与事件传播

    javascript的事件模型可以分为2个级别DOM0,DOM1,DOM2
    (参考:http://www.trans4fun.org/2011/12/%E3%80%90javascript%E4%BA%8B%E4%BB%B6%E7%B3%BB%E5%88%97%E3%80%91dom%E4%BA%8B%E4%BB%B6%E6%9C%BA%E5%88%B6%E7%AE%80%E6%98%8E%E6%95%99%E7%A8%8B/)
    注:这里DOM1级别的似乎有误,没有DOM1级别事件.
    注:似乎有DOM3了,但是貌似跟事件关系不大,可参考http://blog.sina.com.cn/s/blog_825442790101354v.html


    前面说的添加时间处理程序方式(1)(2)(3)中处理方式就是DOM0级别的,

    方式(3)的好处是将JavaScript和HTML分离开来。
    它通过给HTML元素设置一个属性,该属性是一个回调函数来实现事件的注册。
    然而,这种方式给一个元素的同一事件只允许一个处理器。

    方式(4)是DOM级别2,对于DOM级别2的事件最大的好处就是一个事件可以注册许多处理器。
    不仅如此,你还可以指定处理器是在捕获阶段还是冒泡阶段被触发(
    通过设置”addEventListener()”函数的第三个参数来指定 – true表示在捕获阶段,false表示在冒泡阶段)

    (注:没有DOM1级的事件:DOM级别1于1998年10月1日成为W3C推荐标准。
    1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。
    参考:http://blog.ueder.info/333.html)

    事件传播的过程详解:
    (1)DOM0级的事件模型中,浏览器把时间分派给发生事件的文档元素,那个对象具有适合的时间句柄,就运行这个句柄.
    除此之外,不用执行其他操作.(摘自JavaScript权威指南,犀牛书第5版400页.)
    实际测试发现,DOM0级别的方式定义的事件,默认是冒泡的.
    比如下面的代码:
    在div标签的onclick的onclick属性中指定事件处理函数.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk"    />
    <title>浏览器事件机制——冒泡处理</title>
    <style>
         div {border:1px  solid blue;}
         div#divGrandpa {padding:40px;background-color:#f00;}
         div#divFather {padding:40px;background-color:#0f0;}
         div#divSon {padding:40px;background-color:#00f;}
    </style>
    </head>
     <body>
    <div id="divGrandpa" style="300px;height:200px;" onclick="showGrandpa();" > I am Grandpa
           <div id="divFather" style="200px;height:120px;" onclick="showFather();"> I am father
                <div id="divSon" style="100px;height:40px;" onclick="showSon();" >
                    点击我 I am son
                </div>
           </div>
    </div>
    <script>
        function showSon() 
        {
            alert("I am son");
        }
        
        function showFather() 
        {
            alert("I am father");
        }
        
        function showGrandpa() 
        {
            alert("I am Grandpa");
        }
    </script>    
    </body>
    </html>
    View Code

    当点击蓝色部分(son)时,依次触发son,father,grandpa的div的onclick事件,
    可见这个事件传播过程中,事件对象是向上冒泡的.
    这个过程可分解为:
    鼠标单击 -> 浏览器生成单击事件 -> 浏览器把单击事件分派给son(div) -> div(son)执行单击处理函数 ->
    事件对象往上传播(即往document对象传播,往body标签方向传播) -> 传播到 father,执行father的click事件处理函数 ->
    事件对象传播到grandpa,执行grandpa的click事件处理函数.
    (2)DOM2级的事件模型中,事件的传播分三个阶段:
    a.事件捕捉阶段,事件对象沿着document一直传播到发生事件的那个对象(即文档的目标节点,比如id为son的div),这个过程叫事件捕获.
    b.事件到达目标节点,如果目标节点指定了事件处理函数,则执行这个函数
    c.事件自目标节点向上,沿着a相反的方向再次传播到document对象,这个过程叫做事件冒泡.
    使用addEventListener或attachEvent方式注册的事件处理函数,就是这种DOM2级的事件处理函数.
    这里有两个函数是因为addEventListener是标准浏览器中的函数,而attachEvent是IE专用的,不是标准浏览器函数.
    使用addEventListener方式注册事件处理函数后,
    在事件传播过程中的a,b,c三个阶段中经过的节点都有可能执行该节点注册的事件处理函数,比如在过程a中,对于单击事件来说,
    如果目标节点的任何一个祖先节点注册了单击事件处理函数,则在过程a中就有机会执行这个祖先节点的
    单击事件处理函数.

    addEventListener函数调用方式如下:
    grandpa.addEventListener("click", showGrandpa, true);第一个参数是事件名称,第二个参数是事件处理函数名,
    第三个参数为true表示在事件捕获阶段可以执行这个事件处理函数,为false表示不在事件捕获阶段执行该事件处理函数,
    而是在事件冒泡阶段执行时间处理函数(这也是默认的方式,DOM0级别事件处理方式)
    因为第三个参数要么为true要么为false,所以使用addEventListener注册的事件处理函数要么在捕获阶段执行(第三个参数=true),
    要么在冒泡阶段执行(第三个参数=false),
    addEventListener注册的事件处理函数 不会 同时在 捕获和冒泡阶段执行.
    attachEvent方式注册事件处理函数,是IE专用的,非标准.事件传播过程只有b和c,即没有事件捕获过程.
    因为attachEvent注册的事件处理函数只在冒泡阶段执行,所以这个函数没有第三个参数.
    调用方式为:grandpa.attachEvent("onclick", showGrandpa);
    需要注意的是,第一个参数,需要在事件名称前面加上on.
    3. 事件对象
    在执行监听函数时,会传入一个event对象,其实有一些常用的属性我们会经常用到:
    type:
    发生事件的类型,如click , mouseover, mouseout等
    target:
    发生事件的节点可能与currentTarget不同
    currentTarget:
    正在处理事件的节点,如果在capturing阶段和冒泡阶段处理事件,这个属性就与target属性不同。在事件监听函数中应该用这个属性而不是this
    stopPropagation():
    可以阻止事件从当前正在处理他的节点传播
    preventDefault():
    阻止浏览器执行与事件相关的默认动作,与0级DOM中返回false一样
    clientX, clientY:
    鼠标相对于浏览器的x坐标y坐标
    screenX, screenY:
    鼠标相对于显示器左上角的x坐标y坐标
    IE下的处理方式
    IE下没有addEventListener,但是有自己类似的方法:attachEvent,这个方法只有两个参数,第一个参数为事件类型的前面需要加”on”,由于 ie下没有捕获,所以没有类似标准浏览器的第三个参数。
    IE上可以对元素进行多次同样的绑定,标准浏览器只会绑定一次。ie下event对象不是事件处理程序传入的参数,而是全局的变量:window.event,例如中断冒泡用window.event.cancelBubble = true.
    event常用属性
    type:
    兼容DOM的type属性
    srcElement:
    兼容DOM的target属性
    clientX, clientY:
    兼容DOM的clientX, clientY属性
    cancelBubble:
    布尔值,设为true同调用stopPropagation()
    returnValue:
    布尔值,设为false同调用preventDefault()
    卸载方法:
    Object.removeEventListener(eventType,handler,useCapture);//DOM标准的事件卸载方式
    Object.detachEvent(eventType,handler);//IE内核的事件卸载方式
    4 事件传播过程的阻止
    浏览器在执行事件处理函数都会传递一个event对象,改event对象有个
    stopPropagation()方法可以阻止事件对象的传播(阻止捕获和冒泡).

  • 相关阅读:
    解决PKIX:unable to find valid certification path to requested target 的问题
    Linux 上的常用文件传输方式介绍与比较
    用VNC远程图形化连接Linux桌面的配置方法
    红帽中出现”This system is not registered with RHN”的解决方案
    linux安装时出现your cpu does not support long mode的解决方法
    CentOS SSH配置
    es6扩展运算符及rest运算符总结
    es6解构赋值总结
    tortoisegit安装、clon、推送
    es6环境搭建
  • 原文地址:https://www.cnblogs.com/ranran/p/javascript_event.html
Copyright © 2011-2022 走看看