首页 > 网站 > WEB开发 > 正文

JavaScript系列----事件机制

2024-04-27 14:11:05
字体:
来源:转载
供稿:网友

javaScript系列----事件机制

1.事件流

1.1.标准事件流

所谓的标准事件流指的的:EMCAScript标准规定事件流包含三个阶段,分别为事件捕获阶段,处于目标阶段,事件冒泡阶段。

下面是一段html代码,根据代码来说明标准事件流。

<!DOCTYPE HTML><html>    <body>        <div>            <button>click</button>        </div>    </body></html>

在上面的代码中,如果点击按钮button,则标准事件触发分别经历以下三个阶段:

事件触发一次经历三个阶段,所以我们在一个元素上注册事件也就可以在对应阶段注册事件,移除事件也同样。

target.addEventListener(type, listener, useCapture);   //标准注册事件函数                                //target:target: 文档节点、document、window 或 xmlHttPRequest。                                //函数的参数,分别为 注册事件类型---type不包含on,事件的回调函数,事件注册在捕获期间还是冒泡期间                                //例如:给button注册onclick事件,要是在捕获阶段注册,则 button.addEventListener("click",function(){},true);
target.removeEventListener(type, listener, useCapture);  //在某一个元素上撤销已注册的事件。 这里强调的是 这里的函数必须与已注册的函数是同一个函数!

1.2.IE中事件流

虽然大部分的浏览器都遵循着标准,但是在IE浏览器中,事件流却是非标准的。IE中事件流只有两个阶段: 处于目标阶段,冒泡阶段。

上面的HTML结构,如果是在IE中,事件流执行时如图所示:

对应着在IE中的事件注册和撤销事件函数:

target.attachEvent(type, listener);  //target: 文档节点、document、window 或 xmlhttpRequest。                                     //函数参数: type----包含on.type一般为“onclick”,"onkeydown"                                     //          listener:事件触发时的回调函数。
target.detachEvent(type,listener);   //参数与注册参数相对应。

因为,IE中事件流没有捕获阶段,所以相应的在注册事件和撤销事件时比标准注册事件少一个参数。

1.3.事件的执行顺序

  为什么要单独提出事件的执行顺序? 是因为一些事件有其默认的行为,比如在文本框中按下鼠标左键,文本框文本框获得焦点;点击一个超链接,超链接进行跳转。 那么,事件的执行顺序是怎样的呢?

一般事件的执行顺序: 事件的捕获阶段====>处于目标阶段====>事件的冒泡阶段====>事件的默认行为。

正因为事件的默认行为是最后执行的,我们才得以机会阻止事件的默认行为。

如下,阻止文本框获取焦点:

//阻止文本框获取焦点    var input=document.getElementById("inputText");    input.onmousedown=function(event){        event=event||window.event;        if(event.preventDefault){  //非IE浏览器阻止事件默认行为            event.preventDefault();        }else{            event.returnValue=false;//IE浏览器阻止事件默认行为        }    }

1.4.跨浏览器注册事件

因为IE中浏览器注册事件比较特殊,下面是一个跨浏览器注册函数。

var EventUtil =  {    addEventListener: function (element, type, callback) {  //注册事件,因为浏览器的兼容性考虑,注册事件一般都是注册在事件的冒泡阶段        if (element.addEventListener) {            element.addEventListener(type, callback, false);        } else if (element.attachEvent) {            element.attachEvent('on' + type, callback);        } else {            element['on' + type] = callback;        }    },                       removeEventListener: function(element, type, callback) {  //撤销事件        if (element.removeEventListener) {            element.removeEventListener(type, callback, false);        } else if (element.detachEvent) {            element.detachEvent('on' + type, callback);        } else {            element['on' + type] = null;        }    }};

2.DOM事件

2.1DOM0级事件

通过Javascript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序的属性。这种为事件处理程序赋值的方法是在第四代Web浏览器中出现的,而且至今仍然为所有现在浏览器支持。原因主要有两点: 1.简单 2.具有跨浏览器优势。

每个元素(window和document)都有自己的事件处理程序属性,这些属性通常全部小写,例如 onclick, onmousedown.

var btn = document.getElementById('mybtn');btn.onclick = function () {  alert('click');}

DOM0级事件有其自身的局限性,

1.那就是某一个属性只能赋值给一个函数,也就导致在某一个元素上的某一个事件属性只能对应着一个函数。多次注册时,已最 后一次注册为准。

2.DOM0级事件全部都是默认在冒泡阶段执行。

2.2.DOM2级事件

我们在第一部分所定义的跨浏览注册事件函数,就是一个DOM2级注册事件。DOM2级注册事件相比于DOM0级的优势就在于其可以多次注册,并且执行顺序与注册顺序一致。

var btn = document.getElementById('mybtn');function fun1(){ alert("1");}function fun2(){ alert("2");}
EventUtil.addEventListener(btn,"click",fun1);  //注册事件
EventUtil.addEventListener(btn,"click",fun1); //触发事件的时候会 先弹出 1 在弹出 2

如果不考虑IE浏览器,我们还可以在事件的捕获阶段,注册事件,但是一般因兼容性考虑,我们很少在事件的捕获阶段注册事件。

3.事件对象

在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有事件有关的信息。

例如,单击事件中会包含鼠标的位置信息,键盘触发的事件中会包含按下的键位有关的信息。

所有的浏览器都支持event,但支持的方式却有不同。

3.1.标准浏览器中的事件对象

属性 类型 读写描述
bubblesboolean只读返回布尔值,指示事件是否是起泡冒泡
cancelableboolean只读返回布尔值,指示事件是否可拥可取消的默认动作。
currentTargetElement只读返回其事件监听器触发该事件的元素。
eventPhaseIntenger只读返回事件传播的当前阶段。
targetElement只读返回触发此事件的元素(事件的目标节点)。
timeStampDate只读返回事件生成的日期和时间。
typeString只读返回当前 Event 对象表示的事件的名称。
trustedboolean只读该事件是否是浏览器生成(true代表是,false代表是开发人员创建
preventDefaultFunction只读取消事件的默认行为在cancelable=true时有效
stopPropagationFunction只读取消事件的捕获或者冒泡行为在bubbles=true时有效

在事件处理程序内部,对象this始终指向currentTarget的值,而target则只包含事件的实际目标。

3.2.IE中的事件对象

属性 类型 读写描述
cancelBubbleboolean读/写返回布尔值,指示事件是否是起泡冒泡
returnValueboolean读/写返回布尔值,指示事件是否可拥可取消的默认动作。
srcElementElement只读返回其事件监听器触发该事件的元素。
typeString只读被触发事件的类型

上面的这些属性,是任何一个事件均会具有的属性。

在IE中有些srcElement对应着target;

执行event.returnValue=false对应着event.preventDefault();

执行event.cancelBubble=true对应着event.stopPropagation();

同时对于一些相关属性IE 比如 relatedTarget属性对应IE中的fromElement和toElement.属性.

3.3.跨浏览器事件对象

因为IE和标准浏览器的不同,所以为了克服这样或者那样的问题,现在编写一个工具包克服兼容性的问题:

 1 var EventUtil =  { 2         addEventListener: function (element, type, callback) {  //注册事件,因为浏览器的兼容性考虑,注册事件一般都是注册在事件的捕获阶段 3             if (element.addEventListener) { 4                 element.addEventListener(type, callback, false); 5             } else if (element.attachEvent) { 6                 element.attachEvent('on' + type, callback); 7             } else { 8                 element['on' + type] = callback; 9             }10         }, 11         getEvent:function(event){           //获取事件12             return event||window.event;13         },                14         getTarget:function(event){           //获取事件的触发目标15             return event.target||event.srcElement;16         },17         preventDefault:function(event){        //阻止事件的默认行为18             event.preventDefault?event.preventDefault():event.returnValue=false;19         },20         stopPropagation:function(event){          //阻止事件冒泡21             event.stopPropagation?event.stopPropagation:event.cancelBubble=true;22         },23         removeEventListener: function(element, type, callback) {  //撤销事件24             if (element.removeEventListener) {25                 element.removeEventListener(type, callback, false);26             } else if (element.detachEvent) {27                 element.detachEvent('on' + type, callback);28             } else {29                 element['on' + type] = null;30             }31         }32     };

每个事件在其被触发时,都有一些其特有的属性,比如键盘事件会有键位信息,鼠标事件会有会有位置信息。onmouseenter事件会有fromElement(IE)中,relatedTarget(非IE);onmouSEOver事件会有toElement(IE)中,relatedTarget(非IE).

详情在W3C教程中有进一步的叙述。W3C事件详解

4.自定义事件

4.1.模拟鼠标事件

非IE浏览器

创建鼠标事件的方法是createEvent()传入字符串“MouseEvent”.返回的对象有initMouseEvent()方法,这个方法有15个参数,分别与鼠标事件中某个典型的属性一一对应。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表