JS学习12(事件)

本文深入探讨了JavaScript中的事件流,包括事件冒泡、事件捕获和DOM事件流的概念。事件处理程序分为HTML事件处理程序、DOM0级和DOM2级事件处理程序,每种都有其特点和使用场景。此外,文章还讲解了事件对象、事件类型以及如何处理内存和性能问题,如事件委托和移除事件处理程序。对于开发者来说,理解和掌握这些概念对于构建交互式Web应用至关重要。
摘要由CSDN通过智能技术生成

事件流

IE和Netscape开发团队提出了完全相反的两种事件流的概念,事件冒泡流和事件捕获流。

事件冒泡

事件由最具体的元素开始,逐级向上传播到较不具体的元素,最终到文档。

事件捕获

事件捕获从document开始,逐级向下,最后传到最具体的节点。

DOM事件流

DOM2级事件定义的事件流包含3个阶段:事件捕获阶段,处于目标阶段,事件冒泡阶段。
捕获阶段会从文档节点自上而下传递直到目标节点的上一个节点;处于目标阶段时传到目标节点,冒泡阶段开始向上传递知道文档节点。
规定是捕获阶段事件不传递到目标节点,但是大多数浏览器就传递到了,这就意味着有2次机会在目标对象上操作事件。

事件处理程序

响应某个事件的函数

HTML事件处理程序

可以使用HTML特性来指定。

<input type="button" value="Click Me" onclick="alert(event.type)">
<input type="button" value="Click Me" onclick="alert(this.value)">
<input type="button" value="hahaah" onclick="clickButton(this)">
function clickButton(element) {
    alert(element.value);
}

这里注意JS代码中如果出现&”“<>要使用转义字符。
这样写事件处理程序是很不灵活的,HTML代码和JS代码耦合度太高。
不过这样写是有一些方便的地方的,这样写的JS语句会被包含在一个动态创建的函数中,这个函数中会存在一个局部变量event事件对象,而且通过this这个变量可以访问到元素本身。这个函数还会使用with拓展作用域,让你更方便的直接访问document及元素本身的成员:

function(){
   
    with(document){
        with(this){ 
            //你的代码   
        } 
    }
}
//于是可以直接这样写
<input type="button" value="Click Me" onclick="alert(value)">

如果要调用函数,这个函数在JS中要处于全局作用域哦,而且要使用this对象要将this作为参数传进去,否则是访问不到的。
这样写事件处理程序是有问题的,一个是紧耦合的问题,一个是时间差,如果你的JS文件是放在最下面的,有可能会出现函数已经绑在事件上了可是JS却还没给出函数定义,这样就会报错,为了避免这样的情况出现,我们使用try-catch:

<input type="button" value="Click Me" onclick="try{clickButton(this);}catch(ex){}">

不过还是不那么理想是吧。

DOM0级事件处理程序

每个元素都有自己的事件处理程序属性,以这种方式添加的事件会在事件流的冒泡阶段被处理。传入的处理函数是在元素的作用域中运行。将这个属性指向空就取消了事件绑定,值得一提的是,如果你使用上面的HTML特性指定事件处理函数,这个属性里就包含着HTML里你写的事件函数的代码,置空也同样可以取消绑定。

var btn = document.getElementById("myBtn");
btn.onclick = function(){
   
    alert(this.id);    //"myBtn"
};
btn.onclick = null;

DOM2级事件处理程序

IE8及以下不支持DOM2级事件
DOM2级事件定义了两种方法:addEventListener() removeEventListener()。这两个方法接受3个参数,要处理的事件名,处理函数,和一个布尔值。这个布尔值代表在捕获节点调用事件处理程序(true)还是在冒泡过程中调用。
这样添加意味着可以添加多个事件处理程序,在事件触发时会按照添加的顺序来执行。传入的处理函数是在元素的作用域中运行。
注销时要传入完全相同的函数才能注销,这就意味着如果你的处理函数是以匿名函数的方式传递进去的,那就不可能注销了哦,因为再传进去一个匿名函数也不是原先那个了:

var btn = document.getElementById("myButton");
var body = document.body;

//冒泡阶段
body.addEventListener("click", function(){
   
    alert("Hello world!");
}, false);
//捕获阶段
body.addEventListener("click", function(){
   
    alert("Hello world!");
}, true);
//如果是使用匿名函数注册的
btn.addEventListener("click", function(){
   
    alert(this.id + "匿名");
}, false);
//注销不掉
btn.removeEventListener("click", function(){
   
    alert(this.id);
}, false);
//这样就能注销掉了
var handler = function(){
   
    alert(this.id + "非匿名");
};
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);

IE事件处理程序

IE8及以下不支持DOM2级事件,但是支持两个类似方法attachEvent()、detachEvent()
只支持冒泡阶段
传入的处理函数是在全局作用域中运行
添加多个事件时触发顺序与添加顺序相反
注销时同样需要传入相同的参数,匿名函数无法注销。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
   
    alert(this === window); //true
});
var handler = function(){
   
    alert("Clicked");
};
btn.attachEvent("onclick", handler);
btn.detachEvent("onclick", handler);

跨浏览器事件处理程序

优先使用DOM2级的,再不行使用IE专有的,最后使用DOM0级的(一般不可能用到)

var EventUtil = {
    addHandler: function(element, type, handler){
   
        if (element.addEventListener){
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent){
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    },
    removeHandler: function(element, type, handler){
   
        if (element.removeEventListener){
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent){
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null;
        } }
};
var btn = document.getElementById("myButton");
var handler = function(){
    alert("Clicked");
};
EventUtil.addHandler(btn, "click", handler);
EventUtil.removeHandler(btn, "click", handler);

事件对象

事件被触发时会产生一个事件对象,这个对象中包含着所有与事件有关的信息,包括导致事件的元素,事件的类型以及其他各个事件特定的信息。所有浏览器都支持event对象,但是实现不同。

DOM中的事件对象

兼容DOM的浏览器会将一个event对像传入到事件处理程序中,三种方式都有

btn.onclick = function(event){ 
    alert(event.type); //"click"
};
btn.addEventListener("click", function(event){
    alert(event.type); //"click" 
}, false);
<input type="button" value="Click Me" onclick="alert(event.type)"/>

所有的event对象都会有下面的方法:

属性/方法 类型 读写 说明
bubbles Boolean 只读 事件是否冒泡
cancelable Boolean 只读 是否可以取消
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值