了解事件处理模型 | 8月更文挑战

314 阅读4分钟

这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战

前言

仅接着上篇!不知道有没有发现,在绑定事件处理函数的时候,处理函数有个参数e或者叫event,其实是一个事件对象

事件对象

事件对象就是处理函数里面的一个参数,说白了就是浏览器打包好的一个对象自动传入到处理函数的第一个参数中

为了兼容IE一般这么写:e = e || window.event

事件对象会有个属性target,这个target叫事件源对象,记录可事件具体在谁身上触发的那个源头 同样IE上事件源对象是e.srcElement,谷歌两个都有

所以为了兼容IE一般获取事件源对象是这么来写:

e = e||window.event;
var target = e.target || e.srcElement;

事件处理模型

当浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件?想象画在一张纸上的一组同心圆。如果把手指放在圆心上,那么手指指向的不是一个圆,而是纸上的所有圆

两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。如果单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,甚至也单击了整个页面

但有意思的是,IE和Netscape开发团队居然提出了差不多是完全相反的事件流的概念。IE的事件流是事件冒泡流,而Netscape的事件流是事件捕获流。事件冒泡和事件捕获称为两种事件处理模型 #事件冒泡和事件捕获

IE的事件流叫做事件冒泡(event bubbling),事件冒泡是结构上(非视觉上)嵌套的函数存在事件冒泡功能,即同一事件自子元素冒泡向父元素(自底向上) [注意]所有现代浏览器都支持事件冒泡

但在具体实现在还是有一些差别。IE9、Firefox、Chrome、Safari将事件一直冒泡到window对象

而事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前就捕获它

即事件捕获是指:结构上(非视觉上)嵌套的元素存在事件捕获功能,即同一事件自父元素冒泡向子元素(自顶向下)

注意IE上没有事件捕获,Chrome和新版本的Firefox等都实现了

一个dom元素的一个事件类型绑定的一个处理函数只能存在一种事件模型,要么事件冒泡要么事件捕获。正常的通过addEventListener(type,fn,false)绑定事件时,最后一个参数默认是false表示的是,事件冒泡模型。如果改成true,立即变成事件捕获模型

如果一个dom元素的一个事件类型绑定了两个处理函数,两个函数的事件处理模型一个是事件冒泡一个是事件捕获,触发顺序是先捕获,后冒泡。

focus、blur、change、submit、reset、select等事件类型不冒泡

可以 利用事件冒泡和事件源对象可以叫事件委托给父元素

事件委托机制

利用事件冒泡和事件源对象进行处理

优点

  • 性能好,不需要循环所有元素一个个绑定事件
  • 灵活,当有其他新的子元素时,不需要重新绑定事件。

取消冒泡

有的时候,我们不希望有冒泡功能,那我们怎么取消事件冒泡呢?

  1. e.stopPropagation(); W3C标准方法,IE8及以下不兼容

  2. e.cancelBubble = true ; IE独有,新版本Chrome也实现了

封装一个都好使的取消冒泡函数

function _stopBubble(e){
  e = e || e.
  e.stopPropagation() ? e.stopPropagation() : e.cancelBubble =  true;
}

组织默认事件

有的时候我们需要阻止一些浏览器默认的事件

比如:表单提交、a链接跳转、右键菜单等

有几种方式:

  1. return false;以对象属性的方式注册的事件才生效
  2. e.preventDefault(); w3c标准,IE8及其以下不兼容
  3. e.returnValue = false; IE使用 封装阻止默认事件的函数
function cancelDefault(e){
  e = e || window.event;
  if(e.preventDefault){
    e.preventDefault();
  }else{
    e.returnValue =  false;
  }
}

结束语

我是前端新手Andy_W,如有问题,欢迎指正。也希望点赞支持!!