前言

新的一天又开始了,我们对今天对未来抱有很大期待,所以开始我们今天的学习吧,在此之前来点题外话,还是爱好问题。

周三的面试虽然失败,但是也是很有启迪的,比如之前我就从来没有想过爱好问题,我发现我的爱好如下:

① 霹雳布袋戏

完了就米有什么爱好了,其实我完全可以说自己爱好旅游什么的,我也确实爱好旅游,只不过比较穷,走的地方不多罢了,这里又扯出一个话题:

学习工作与生活

我们为了理想需要学习需要工作,工作完了需要生活,现在是前者分量掩盖了后者,所以以后的世界要注意了。

好了进入今天的学习吧,我们今天来看看javascript里面的事件吧。

事件交互

javascript与html之间的交互是通过事件实现的,我们使用侦听器注册事件,
在事件发生时候便执行相关的代码,这就是传说中的观察者模式

事件流

事件捕获与冒泡的出现十分有意思,当浏览器发展到第四代时(IE4),出现了一个小意思的问题:

页面的哪一部分有什么事件?浏览器开发团队也不知道了,想象我们页面的元素:

 <div>
<a>刀狂剑痴<span>叶小钗</span> </a>
</div>

我们点击span时候是不是也点击了a呢?点击a是不是也点击了div呢,依次上升到body与html

事件流描述的是从页面中接收事件的顺序
IE采用事件冒泡流
标准采用事件捕获流
最后addEventLister给出了第三个参数同时支持冒泡与捕获

事件冒泡

由span开始一直传播至document

事件捕获

由document向下传播至span

事件处理程序

事件就是用户或者浏览器自身执行某种动作,比如click、load、mouseover。
而响应某个事件的函数就叫做事件处理程序(事件监听器),事件处理程序的名字以on开头,click=>onclick、load=>onload
 el.addEventListener(eventType, function () {

 }, false);

 该方法应用至dom节点
第一个参数为事件名
第二个为事件处理程序
第三个为布尔值,true便是事件捕获,false为事件冒泡

既然都说到了addEventLister,我们来看一看这段代码吧:

 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div>
<a>刀狂剑痴<span id="el">叶小钗</span> </a>
</div>
<script type="text/javascript">
var el = document.getElementById('el');
el.addEventListener('click', function () {
alert('冒泡');
}, false);
el.addEventListener('click', function () {
alert('捕获');
}, true);
</script>
</body>
</html>

我们同时给一个dom绑定了click事件,并且一个是冒泡,一个是捕获,我们的执行顺序是怎么样的呢?

答案一:先冒泡再捕获

但是答案真的是这样的吗?我们将代码改下:

 var el = document.getElementById('el');
el.addEventListener('click', function () {
alert('捕获');
}, true);
el.addEventListener('click', function () {
alert('冒泡');
}, false);

如此一来便是先捕获再冒泡了,我想说这道题真的好耍赖啊。。。。

那么现在我们是离真相近了还是远了呢?其实真相依旧扑所迷离:

 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div>
<a id="p">刀狂剑痴<span id="el">叶小钗</span> </a>
</div>
<script type="text/javascript">
var el = document.getElementById('el');
var p = document.getElementById('p');
//el.addEventListener('click', function () {
// alert('捕获');
//}, true);
//el.addEventListener('click', function () {
// alert('冒泡');
//}, false);
p.addEventListener('click', function () {
alert('父级 冒泡');
}, false);
p.addEventListener('click', function () {
alert('父级 捕获');
}, true);
</script>
</body>
</html>

此处会出现两种情况:

① 直接点击a标签,便与之前逻辑一致,哪个定义到前面哪个先执行

② 点击span标签情况会有所不同!!!

我们来理一理:

因为我们span标签没有注册事件,我们点击时候他虽然没有反应,但是他也会向上传递的:

 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div>
<a id="p">刀狂剑痴<span id="el" onclick="alert('点击');">叶小钗</span> </a>
</div>
<script type="text/javascript">
var el = document.getElementById('el');
var p = document.getElementById('p'); p.addEventListener('click', function () {
alert('父级 冒泡');
}, false);
p.addEventListener('click', function () {
alert('父级 捕获');
}, true); //el.addEventListener('click', function () {
// alert('捕获');
//}, true);
//el.addEventListener('click', function () {
// alert('冒泡');
//}, false);
</script>
</body>
</html>

我们这个代码执行的顺序是:父级捕获=>点击=>父级冒泡

说明,点击span引发的事件便与事件注册程序的先后无关了,我这里斗胆的猜测一下整个逻辑

标准浏览器默认采用捕获方式,所以:
我们点击span时候,事实上市先点击document然后到span,中间经过了a标签便先执行其逻辑(将事件写到标签中不合适)
 var el = document.getElementById('el');
var p = document.getElementById('p'); p.addEventListener('click', function () {
alert('父级 冒泡');
}, false);
p.addEventListener('click', function () {
alert('父级 捕获');
}, true);
el.addEventListener('click', function () {
alert('冒泡');
}, false);
el.addEventListener('click', function () {
alert('捕获');
}, true);

这段javascript的执行顺序是(点击span):父级捕获=>冒泡=>捕获=>父级冒泡

各位看看这段东西有问题没有,上次要答好寒冬老师这个问题是不可能的。。。

这个问题暂时到这里,若是后面讨论的朋友多我们再研究吧。

【初窥javascript奥秘之事件冒泡】那些年我们一起冒的泡

请使用高版本浏览器

兼容性处理

我们知道这块的兼容性有一点问题,所以我们一般都会封装下的,但是里面的event对象已经target的获取各位就自己想办法处理下吧:

 var EventUtil = {
addHandler: function (el, type, handler) {
if (el.addEventListener) {
el.addEventListener(type, handler, false);
} else {
el.attachEvent('on' + type, handler);
}
},
removeHandler: function (el, type, handler) {
if (el.removeEventListener) {
el.removeEventListerner(type, handler, false);
} else {
el.detachEvent('on' + type, handler);
}
}
};

按道理说,我们本来可以使用call方法将this指向以及event传进去,彻底解决这块兼容问题,但是又涉及到删除时候删不掉而导致性能问题,我们还是老老实实用jquery吧。

真的能写自己框架的话,这块到可以好好研究一番!

事件对象

我们前面经常提到事件对象event,那么他是什么呢?

触发dom上某个事件时,会产生一个事件对象event,这个对象包含着与事件有关的信息
① 导致事件的元素
② 事件类型
③ 特定信息(鼠标信息,键盘信息)
......

这个对象包含太多信息,我这里也记不住,于是挑几个重要的来说吧:

① currentTarget dom 事件处理程序当前正在处理事件的那个元素(始终等于this)

② preventDefault function 取消事件默认行为

③ stopPropagation function 取消事件冒泡

④ target dom 事件的目标(这个与currentTarget不是很好区分哦,currentTarget可能发生变化target却不会)

这里关于currentTarget与target可能有些朋友没有分清楚,我们上个代码吧:

 EventUtil.addHandler(document, 'click', function (e) {
e = window.event || e;
var target = e.target || e.srcElement;
//操作
//此处currentTarget便等于this
//target便是我们点击的元素
alert(e.currentTarget); //HTMLDocument
alert(target); //HTMLSpanElement
});

来吧搞点兼容的代码,反正不吃亏:

 var EventUtil = {
addHandler: function (el, type, handler) {
if (el.addEventListener) {
el.addEventListener(type, handler, false);
} else if (el.attachEvent) {
el.attachEvent('on' + type, handler);
} else {
el['on' + type] = handler;
}
},
removeHandler: function (el, type, handler) {
if (el.removeEventListener) {
el.removeEventListerner(type, handler, false);
} else if (el.detachEvent) {
el.detachEvent('on' + type, handler);
} else {
el['on' + type] = null;
}
},
getEvent: function (e) {
return e ? e : window.event;
},
getTarget: function (e) {
return e.target ? e.target : e.srcElement;
},
preventDefault: function (e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
},
stopPropagation: function (e) {
if (e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
}
};

事件类型

我们一般有这几类事件:

① UI用户界面事件
当用户与页面上元素发生交互时触发 ② 焦点事件
当元素获取/失去焦点时触发 ③ 鼠标事件
鼠标操作引发的事件 ④ 滚轮事件
鼠标滚轮引起的事件,类似的也算 ⑤ 文本事件
text类型的操作 ⑥ 键盘事件
......

我们下面来看看我们的各个事件吧。

UI事件

load事件

当页面全部加载后在window上触发,当所有框架都加载完毕时在框架集上触发,当img加载结束后在img上触发。

javascript中这个家伙非常常见,页面完全加载后(图片、js、css)就会触发,来一个图片加载结束后的提示吧:

 EventUtil.addHandler(img, 'load', function (e) {
e = EventUtil.getEvent(e);
alert(EventUtil.getTarget(e).src + ' 加载结束');
});

PS:此处的加载与我们jquery的document.ready有所不同,一个是图片全部加载结束执行,一个是dom与css形成render树便开始执行,后者是我们希望的。

unload

这个事件与load对应,我们却用到不多,在文档完全卸载后触发(页面切换也会触发)。

这个家伙一般用于释放资源的,我们一般不需要关注。

resize

这个事件我们也用得很多,当浏览器高度或者宽度变化时就会触发(这个时候也会引起页面回流reflow哦),事件在window上触发。

这个事件中的代码可能会被频繁执行,所以定义时候一定要注意。

scroll

滚动条滚动时候触发

焦点事件

① blur: 事情焦点时候触发,不会冒泡

② focus: 获取焦点时候触发,不会冒泡

其它的略去

鼠标事件

事件很多......

后面还有很多新增的事件,我这里先不管啦。。。等接触到移动开发再研究吧,今天暂时这样。

结语

今天我们一起学习了javascript的事件流,各位有所得么?

【追寻javascript高手之路05】理解事件流的更多相关文章

  1. 【追寻javascript高手之路04】理解prototype

    前言 中午时候我去药店称了下体重,好家伙!我减肥成功了,足足比上个月瘦了10斤!于是想减肥就去郑州吧... 然后回来迷迷糊糊睡了一会,居然想起了周三的面试,有点小遗憾有点小触动. 这次回成都后,还没有 ...

  2. 【追寻javascript高手之路03】javascript对象大乱斗

    前言 昨天我们学习了下javascript中函数的参数与作用域的东东,现在回过头来看,其实都是与函数相关的,所以javascript中的函数仍然是王道,我们今天大概会发二篇或者三篇博客一起来巩固我们的 ...

  3. 【追寻javascript高手之路01】javascript参数知多少?

    前言 我最近在思考一个问题,我本身平时还是积累了不少东西,面试时候问的东西基本逃不出写的博客(当然,高级阶段的就不行了),但是真的被问到时我却不一定答得上来. 知道且能回答,回答的效果都不是很好... ...

  4. 【追寻javascript高手之路02】变量、作用域知多少?

    前言 本来想把这个与上篇博客写到一起的,但是考虑到是两个知识点还是分开算了,于是我们继续今天的学习吧. 基本类型与引用类型 ECMAScript的的变量有两种类型: 基本类型(值类型):简单数据段 引 ...

  5. [转]as3事件流机制彻底理解

    题记: 看过网上一些as3事件流的教程,觉得大多都讲得不甚清楚,让人不能直观的理解事件流.而这篇教程以将事件流过程比喻成捕鱼过程,形象简单. 在此基础上对于as3事件流总算有了全面的理解.事件流机制说 ...

  6. DOM事件揭秘-事件流

    事件:文档/窗口中发生的特定的交互瞬间 瀑布流,图片轮播 动作都是通过事件触发的 课程内容: 1,理解事件流 2,使用时间处理程序 3,不同的事件类型 ie4.0以后, 事件流:描述的是从页面中接收事 ...

  7. 深入理解javascript事件流

    摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原 ...

  8. [js高手之路] javascript面向对象写法与应用

    一.什么是对象? 对象是n个属性和方法组成的集合,如js内置的document, Date, Regexp, Math等等 document就是有很多的属性和方法, 如:getElementById, ...

  9. [js高手之路] vue系列教程 - 事件专题(4)

    本文主要讲解事件冒泡,事件绑定的简写,事件默认行为,按键码等一系列与事件相关的知识. 一.事件绑定的简写,@事件类型.  之前我的[js高手之路] vue系列教程 - vue的事件绑定与方法(2) 用 ...

随机推荐

  1. HttpClient post json,可以是数组

    var json = JsonConvert.SerializeObject(obj); StringContent theContent = new StringContent(json, Enco ...

  2. Testing - 测试基础 - 方法

    选择和使用测试方法和工具 按照测试需求用途(或测试技巧)选择 在软件开发生命周期和软件测试流程中适当地选择 按照测试人员实际技能选择 选择可提供的和可执行的 测试方法 类别及技巧 目标 使用方法 举例 ...

  3. SQLServer学习笔记系列3

    一.写在前面的话 今天又是双休啦!生活依然再继续,当你停下来的时候,或许会突然显得不自在.有时候,看到一种东西,你会发现原来在这个社会上,优秀的人很多,默默 吃苦努力奋斗的人也多!星期五早上按时上班, ...

  4. Windows Azure Cloud Service (41) 修改云服务IIS托管管道模式为4.0经典模式

    <Windows Azure Platform 系列文章目录> 这是笔者在之前的项目中遇到的问题,做一下总结,给网友做参考. 在一般情况下,Visual Studio开发的Cloud Se ...

  5. [New Portal]Windows Azure Virtual Machine (20) 关闭Azure Virtual Machine与VIP Address,Internal IP Address的关系(2)

    <Windows Azure Platform 系列文章目录> 默认情况下,通过Azure Management Portal创建的Public IP和Private IP都是随机分配的. ...

  6. java中String的相等比较

    首先贴出测试用例: package test; import org.junit.Test; /** * Created by Administrator on 2015/9/16. * */ pub ...

  7. SQL Server安全(6/11):执行上下文与代码签名(Execution Context and Code Signing)

    在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Se ...

  8. 一篇学习HTTP状态码的神文:我与依依的橙色岁月

    好的,事情是这样的,数年前,我曾有过一段美好的夏日恋情,在此与大家分享. 依依 这个女孩叫做依依 ,她是 80 后的,生日是 1989 年 3 月吧,忘了哪一天了,分手太久了,记不起来了. 转学生 我 ...

  9. 基于MVC4+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式

    在基于MVC4+EasyUI的Web开发框架里面,大量采用了Jquery的方法,对数据进行请求或者提交,方便页面和服务器后端进行数据的交互处理.本文主要介绍利用Jquery处理数据交互的几种方式,包括 ...

  10. 数据库中char, varchar, nvarchar的差异

    char     char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符.    nvarc ...