JavaScript学习--Item35 事件流与事件处理

1. 事件处理

1.1. 绑定事件方式

(1)行内绑定

语法: //最常用的使用方式

<元素 事件=”事件处理程序”>

(2)动态绑定

//结构+样式+行为分离的页面(html+css+js事件)

语法:

对象.事件=事件处理程序

行内绑定和动态绑定的重要区别:

以上程序是不可用的,点击div时,执行test函数,这时,test中的this表示window对象

因为:

我们定义test函数,实际上相应于在window对象下定义了test属性

test(); —> 相当于 window.test();

所以test函数在执行时,里面的this指向window“谁”调用了函数,this指向“谁”


 <html>
    <head>
        <script>

            window.onload=function(){
                document.getElementById(‘btnok‘).onclick=function(){
                    alert(‘hello‘);
                };
                //2、动态绑定
                document.getElementById(‘div1‘).onclick=test;
            };
        </script>
    </head>
    <body>
            <input type=‘button‘ id=‘btnok‘ value=‘确定‘>

            <script>
                function test(){
                    this.style.color=‘red‘;
                }
            </script>
            <div id=‘div1‘>javascript</div>

    </body>
</html>

以上程序是可用的,对象.onclick 在执行test函数时,test函数指向div1元素

1.2 事件监听

我们能不能为一个dom对象的同一个事件指定多个事件处理程序?

例1:通过这题,我们发现,如果为一个对象的同一个事件指定多个事件处理程序,那么,后面指定的程序会覆盖前面的。

<body>
    <script>
        function fn1(){
            alert(‘first‘);
        }
        function fn2(){
            alert(‘second‘);
        }
        window.onload=function(){
            document.getElementById(‘div1‘).onclick=fn1;
            document.getElementById(‘div1‘).onclick=fn2;
        };
    </script>
    <div id=‘div1‘>test</div>
 </body>

如果我们想为一个对象的某个事件指定多个事件处理,可以考虑使用事件监听

事件监听语法:

IE:
    attachEvent(type,callback)
        type:事件名  如:onclick、onsubmit、onchange等
        callback:事件处理程序

基于W3C模型:
    addEventListener(type,callback,capture)
        Type:事件名 ,没有“on”前缀  如:click、submit、change
        Callback:事件处理程序
        Capture:事件模型 (可选参数)   (冒泡模型、捕捉模型) true:捕捉模型
                                                         false:冒泡模型 (默认值)

代码示例:

<body>
    <script>
        function fn1(){
            alert(‘first‘);
        }
        function fn2(){
            alert(‘second‘);
        }
        window.onload=function(){
            document.getElementById(‘div1‘).attachEvent(‘onclick‘,fn1);
            document.getElementById(‘div1‘).attachEvent(‘onclick‘,fn2);
        };
    </script>
    <div id=‘div1‘>test</div>
 </body>

W3c:

<body>
    <script>
        function fn1(){
            alert(‘first‘);
        }
        function fn2(){
            alert(‘second‘);
        }
        window.onload=function(){
            document.getElementById(‘div1‘).addEventListener(‘click‘,fn1);
            document.getElementById(‘div1‘).addEventListener(‘click‘,fn2);
        };
    </script>
    <div id=‘div1‘>test</div>
 </body>

总结:

IE和W3C事件监听的不同:

  1. 监听方法不同:IE attachEvent 、W3C addEventListener
  2. 监听参数不同:IE 没有模型参数、W3C有模型参数 ,默认flase,为事件冒泡。
  3. 触发顺序:IE 8及以下的浏览器触发时是先绑定、后触发 W3C浏览器是先绑定、先触发
  4. 事件名称不同:IE事件需要”on”前缀,W3C不需要’on’前缀

解决事件监听的兼容性问题:

2. 事件流

2.1 事件模型

事件模型(事件的触发顺序)分为两种:Body嵌套div1,div1嵌套div2,div2嵌套div3

1)冒泡模型

2)捕捉模型

目前,IE只支持冒泡模型

2.2 事件冒泡

事件冒泡是指事件响应时会上水冒一样上升至最顶级元素。

简单点说。冒泡就是从下往上,像鱼吐泡,泡泡是从下往上升的,也就是DOM元素被触法事件时(此时的dom元素为目标元素),目标元素事件执行后,它的祖先元素所绑定的事件会向上顺序执行。

如下代码,有四个div嵌套元素,均绑定了click事件,addEventListener函数的第三个参数设置为false说明不为捕获事件,即为冒泡事件。该代码执行结果如下:

<div id="one" style="height: 100px;background: black;">
  <div id="two" style="height: 50px;background: blue;">
    <div id="three" style="height: 30px;background: green;">
      <div id="four" style="height: 10px;background: red;">
      </div>
    </div>
  </div>
</div>
<script type=‘text/javascript‘>
  var one=document.getElementById(‘one‘);
  var two=document.getElementById(‘two‘);
  var three=document.getElementById(‘three‘);
  var four=document.getElementById(‘four‘);
  one.addEventListener(‘click‘,function(){
    alert(‘one‘);
  },false);
  two.addEventListener(‘click‘,function(){
    alert(‘two‘);
  },false);
  three.addEventListener(‘click‘,function(){
    alert(‘three‘);
  },false);
  four.addEventListener(‘click‘,function(){
    alert(‘four‘);
  },false);
</script>

点击one元素,输出one;

点击two元素,输出two one;

点击three元素,输出 three two one;

点击four元素,输出 four three two one;

2.3事件捕获

而冒泡则相反。当触发目标元素时,会从目标元素的最顶层的祖先元素事件往下执行到目标元素为止。

将上面的代码第三个参数均改为true,则执行结果如下:

  • 点击one,输出one;
  • 点击two,输出one two;
  • 点击three,输出one two three;
  • 点击four,输出one two three four;

很明显执行顺序是不同的。

以上便是冒泡和捕获的基本理解。

2.4 w3c事件模型执行原理

首先要了解事件处理的三个阶段:事件捕获—-》目标阶段—-》事件冒泡阶段

也就是说,任何发生在 w3c事件模型 中的事件,无论是冒泡事件还是捕获事件,元素都会先进入捕获阶段,直到达到目标元素,再进入冒泡阶段。

1. 捕获阶段

当我们在 DOM 树的某个节点发生了一些操作(例如单击、鼠标移动上去),就会有一个事件发射过去。这个事件从 Window 发出,不断经过下级节点直到目标节点。在到达目标节点之前的过程,就是捕获阶段(Capture Phase)。

所有经过的节点,都会触发这个事件。捕获阶段的任务就是建立这个事件传递路线,以便后面冒泡阶段顺着这条路线返回 Window。

监听某个在捕获阶段触发的事件,需要在事件监听函数传递第三个参数 true。

element.addEventListener(<event-name>, <callback>, true);

2. 目标阶段(Target Phase)

当事件跑啊跑,跑到了事件触发目标节点那里,最终在目标节点上触发这个事件,就是目标阶段。

需要注意的时,事件触发的目标总是最底层的节点。

3. 冒泡阶段(Bubbling Phase)

当事件达到目标节点之后,就会沿着原路返回,由于这个过程类似水泡从底部浮到顶部,所以称作冒泡阶段。

仍然以上面的代码为例子,假设目标元素为four,也就是four被点击,执行结果是一样,那么它的执行过程呢?

如下代码:

one.addEventListener(‘click‘,function(){
    alert(‘one‘);
},true);
two.addEventListener(‘click‘,function(){
    alert(‘two‘);
},false);
three.addEventListener(‘click‘,function(){
    alert(‘three‘);
},true);
four.addEventListener(‘click‘,function(){
    alert(‘four‘);
},false);

其实过程就是,从four元素的最顶层的祖先开始向下判断是否有捕获事件的元素,从上往下,如有捕获事件,则执行;一直向下到目标元素后,从目标元素开始向上执行冒泡元素,即第三个参数为false的绑定事件的元素。(在向上执行过程中,已经执行过的捕获事件不再执行,只执行冒泡事件。)

此时点击four元素,four元素为目标元素,one为根元素祖先,从one开始向下判断执行。

  • one为捕获事件,输出one;
  • two为冒泡事件,忽略;
  • three为捕获时间,输出three;
  • four为目标元素,开始向上冒泡执行,输出four;(从此处分为两部分理解较容易。)
  • three为捕获已执行,忽略;
  • two为冒泡事件,输出two;
  • one为捕获已执行,忽略。

最终执行结果为:one three four two 。简单理解就是先从上到下输出ture的,然后在反过来输出flase的。

(在这里可能会有疑问,目标元素是什么事件有区别吗?我的测试结果是没有区别的,无论目标元素是捕获还是冒泡,在w3c下都是先从根元素执行捕获到目标元素,再从目标元素向上执行。)

有疑问的话可以在这个例子上将其他三个元素作为目标元素测试。

例如,three作为目标元素,执行结果为:one three two(因为two是冒泡事件,在向下执行时没有执行到。)

2.5 多个事件绑定的执行顺序

最后就是讨论一个DOM元素绑定多个事件的执行过程。

执行次数:绑定了几个事件便执行几次。

如下代码,two元素绑定了两个不同事件,点击two都会执行这两个事件。而执行顺序有所差异

1、如果two为目标元素,目标元素的事情按顺序执行,而其他元素根据W3C的标准执行,即先捕获后冒泡。

【是目标元素】点击two执行结果:one(因为是two的父元素支持捕获事件所以先执行) two,bubble two,capture(顺序执行,注意逗号不是间隔,是输出内容。)

2、如果目标元素不是two,则two的两个事件按先捕获后冒泡触发执行,也就是跟前面讨论的执行过程是一样的,只不过两个事件都绑定在同一个DOM元素上。

【不是目标元素】点击three执行结果:one—— two,capture—– three,bubble———-two,bubble

one.addEventListener(‘click‘,function(){
    alert(‘one‘);
},true);
two.addEventListener(‘click‘,function(){
    alert(‘two,bubble‘);
},false);
two.addEventListener(‘click‘,function(){
    alert(‘two,capture‘);
},true);
three.addEventListener(‘click‘,function(){
    alert(‘three,bubble‘);
},true);
four.addEventListener(‘click‘,function(){
    alert(‘four‘);
},true);

大多数情况下,程序需要对事件冒泡进行取消?

取消事件冒泡

IE:

window.event.cancelBubble=true;

W3C:

function(event){
    event.stopPropagation();
}

解决兼容性问题: public.js

3. 事件对象

1)什么是事件对象

事件对象就是事件发生时系统自动产生的对象,这个对象包含了这个事件发生时所有的信息

如:鼠标移动,那么,鼠标所在的横、纵坐标就保存到了这个事件对象中。

2)如何获得事件对象

IE9及以上版本、W3C:

  • function(event){}

IE8及以下:

  • window.event

默认行为

有些html元素,有自己的行为,如,提交按钮、超链接

有些时候,我们需要对默认行为进行取消,如表单按钮点击时,用户资料添写不完整,我们这时需要将按钮的默认行为取消。

代码示例:

解决兼容性:

4. 事件类型

Web 浏览器中可能发生的事件有很多类型,常用的事件流

  • onLoad :页面加载完毕后 一般用于body元素
  • onUnload :页面关闭后 一般用于body元素
  • onBlur :失去焦点
  • onFocus :获得焦点
  • onClick :点击
  • onMouseOver :当鼠标经过时
  • onMouseOut :当鼠标离开时
  • onMouseDown :当鼠标按下时
  • onMouseUp :当鼠标抬起时
  • onMouseMove :当鼠标移动时
  • onChange :当内容改变时
  • onSelect :当内容被选中时
  • onkeypress :当键盘点击时
  • onkeydown :当键盘按下时
  • onkeyup :当键盘抬起时
    • 触发顺序:onkeydown、onkeypress、onkeyup
    • Onkeypress事件无法捕获功能键
  • onSubmit :当表单提交时
  • onReset :当表单重置时

5. 事件委托(事件代理)

对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事

件处理程序,就可以管理某一类型的所有事件。例如,click 事件会一直冒泡到document 层次。也就

是说,我们可以为整个页面指定一个onclick 事件处理程序,而不必给每个可单击的元素分别添加事

件处理程序。以下面的HTML 代码为例。

<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>

其中包含3 个被单击后会执行操作的列表项。按照传统的做法,需要像下面这样为它们添加3 个事

件处理程序。

var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
EventUtil.addHandler(item1, "click", function(event){
    location.href = "http://www.wrox.com";
});
EventUtil.addHandler(item2, "click", function(event){
    document.title = "I changed the document‘s title";
});
EventUtil.addHandler(item3, "click", function(event){
    alert("hi");
});

如果在一个复杂的Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不清的代码用于添加事件处理程序。此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示。

var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    switch(target.id){
        case "doSomething":
            document.title = "I changed the document‘s title";
            break;
        case "goSomewhere":
            location.href = "http://www.wrox.com";
            break;
        case "sayHi":
            alert("hi");
            break;
    }
});

如果可行的话,也可以考虑为document 对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件。

优:

  • (1)事件绑定函数。每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。可以节省大量内存的占用,减少事件注册,table—代理td
  • (2)新增子元素时,无需进行事件保定,动态部分很适合。
  • (3)不代理的话,必须事先指定所有事件处理程序而导致的DOM访问次数增加,会延迟整个页面的交互就绪时间。

    缺:不能什么都代理,很可能事件误判,劲酒虽好,不要贪杯哦

时间: 2024-10-31 14:02:23

JavaScript学习--Item35 事件流与事件处理的相关文章

JavaScript学习之事件

1 基本概念 1.1 事件 JavaScript与HTML之间的交互是通过事件实现的. 事件是文档或浏览器窗口中发生的一些特定的交互瞬间,在事件上可以注册处理程序,以便当事件发生时,处理程序中的代码得到执行(这种模型对应设计模式中的观察者模式). 1.2 事件流 事件流描述的是从页面接受事件的顺序. 2 事件流 2.1 事件冒泡 IE事件流叫做事件冒泡,即事件开始由最具体的元素接受,然后逐渐向上传播到较为不具体的节点. 事件冒泡能够被所有浏览器支持.注意IE5.5及更早版本的事件冒泡会跳过<ht

JavaScript 进阶教程一 JavaScript 中的事件流 - 事件冒泡和事件捕获

先看下面的示例代码: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>JavaScript 中的事件冒泡与事件捕获</title> </head> <body> <div id="Red" style="width:200px;height:200px;background-color:red;padding:2

理解JavaScript中的事件流

原文地址:http://my.oschina.net/sevenhdu/blog/332014 目录[-] 事件冒泡 事件捕获 DOM事件流 当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆.两家公司的开发团队在看待浏览器事件方面还是一致的.如果你单击了某个按钮,那么同时你也单击了按钮的容器元素,甚至整个

JavaScript 中的事件流和事件处理程序(读书笔记思维导图)

JavaScript 程序采用了异步事件驱动编程模型.在这种程序设计风格下,当文档.浏览器.元素或与之相关的对象发生某些有趣的事情时,Web 浏览器就会产生事件(event). JavaScript 与 HTML 之间的交互是通过事件实现的.事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,或者说事件就是 Web 浏览器通知应用程序发生了什么事情.可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码. 以下是<JavaScript高级程序设计>中事件流和事件处理程序的总结:

JavaScript学习笔记——事件

javascript事件基础和事件绑定 一.事件驱动 1.事件 javascript侦测到的用户的操作或是页面的一些行为(怎么发生的) 2.事件源 引发事件的元素.(发生在谁的身上)3.事件处理程序 对事件处理的程序或是函数 (发生了什么事) 二.事件的分类 1.鼠标事件 onclick ondblclick onmousedowm onmouseup onmousemove onmouseover onmouseout 2.键盘事件 onkeyup onkeydown onkeypress 鼠

【JavaScript学习】-事件响应,让网页交互

什么是事件: JavaScript 创建动态页面.事件是可以被 JavaScript 侦测到的行为. 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件. 比如说,当用户单击按钮或者提交表单数据时,就发生一个鼠标单击(onclick)事件,需要浏览器做出处理,返回给用户一个结果. 主要事件表: 事件1:onclick 说明:onclick是鼠标单击事件,当在网页上单击鼠标时,就会发生该事件.同时onclick事件调用的程序块就会被执行,通常与按钮一起使用. 实例代码:

JavaScript 学习笔记— —事件委托

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> //事件委托:利用冒泡的原理,把事件加到父级上,触发执行效果 //好处 //1.提高性能 //2.新添加的元素,还会有之前的事件 //event

JavaScript学习之事件委托

1 内存和性能 在JavaScript中,添加到页面上的事件处理程序的数量直接关系到页面的整体运行性能: 首先,每个函数都是对象,都会占用内存:内存中的对象越多,性能就越差. 其次,必须事先指定所有事件处理程序,会导致DOM访问次数增加,会延迟整个页面的交互就绪时间. 2 事件委托 事件委托就是事件目标本身不处理事件,而是把处理任务委托给其父元素或祖先元素.事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. 事件委托解决了"事件处理程序过多"的问题. 假定现

JavaScript学习——JS事件总结

回顾之前已经使用过的事件 (onsubmit.onclick.onload.onfocus.onblur.onmouseover.onmouseout) onfocus/onblur:聚焦离焦事件,用于表单校验的时候比较合适(出现"用户名必填"等等) onclick/ondblclick:鼠标单击和双击事件 onkeydown/onkeypress:搜索引擎使用较多 onload:页面加载事件,所有的其它操作(匿名方式)都可以放到这个绑定的函数里面去.如果是有名称,那么在html页面中