JavaScript事件模型

  在各种浏览器中存在三种事件模型: 原始事件模型 , DOM2事件模型 , IE事件模型。

其中原始的事件模型被所有浏览器所支持,而DOM2中所定义的事件模型目前被除了IE以外的所有主流浏览器支持.

  原始事件模型:

 在原始事件模型中(也有说DOM0级),事件发生后没有传播的概念,没有事件流。事件发生,处理,结束,就这么简单。监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。书写方式有两种:

    (1)   HTML代码中指定属性值:<input type=”button” onclick=”func()” />

    (2)   在js代码中指定属性值:document.getElementsByTagName(‘input’)[0].onclick = func

    优点:所有浏览器都兼容

    缺点:

      1.逻辑与显示没有分离

      2.相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的

      3.无法通过事件的冒泡、委托等机制。

DOM2事件模型

    此模型是W3C制定的标准模型。W3C制定的事件模型中,一次事件的发生包含三个过程:

    (1)事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。

    (2)事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数.

    (3)事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行。

    所有的事件类型都会经历 "事件捕获阶段" 但是只有部分事件会经历 "事件冒泡阶段" 阶段,例如submit事件就不会被冒泡。

e.target与e.currentTarget是干什么的?

  e.target获取当前实际触发事件节点,e.currentTarget获取获取当前监听节点。

<div>
<span>11111</span>
</div> $('div').on('click', function(e){
console.log(e.currentTarget);
console.log(e.target);
})

如果点击span的输出:

  li对象

span对象

点击li的非span区域,输出

li对象

li对象

preventDefault与stopPropagation是干什么的

  preventDefault取消事件默认动作,如下例,页面不会跳转

<a href='baidu.com' onclick="stop(e)">

//js:
function stop(e){
e.preventDefault();
}

  stopPropagation阻止元素冒泡,下例 点击child div,parent 的 alert 不会执行

<div id="parent" onclick="alert(this.id)" >

     <div id="child" onclick="doSomething();" ></div>

</div>

//js
function doSomething(e){
e.stopPropagation()
}

  

什么是dispatchEvent?

  dispatchEvent是js的事件触发器,事件触发器就是用来触发某个元素下的某个事件。

可以自定义事件,通过触发器触发。

document.addEventListener('test', function(e){
console.log(e.msg)
});
var e = document.createEvent('HTMLEvents');
e.initEvent('test', true, true);
e.msg = ' test dispatchEvent';
document.dispatchEvent(e); //最终输出 test dispatchEvent

如何实现事件代理,封装一个方法:

  首先介绍一下JavaScript的事件代理。事件代理在JS世界中一个非常有用也很有趣的功能。

当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数,

这主要得益于浏览器的事件冒泡机制。

  以下封装一个简单的实现,只支持id绑定和节点选择

<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
<div>div</div>
</ul> <script>
function delegation(id, node, event, cb) {
var el = document.getElementById(id);
el.addEventListener(event, function(e){
if(e.target.nodeName.toLocaleLowerCase() == node.toLocaleLowerCase()){
cb && cb(e);
}
})
} delegation('list', 'li', 'click', function(e){
console.log(e.target.textContent);
})
</script>

  

事件代理的问题:

  <li><span></span></li>如果同时给span与li绑定事件该如何阻止冒泡???

  代码如下:事件代理同时绑定了li和span,当点击span的时候,li和span都会冒泡。

<li>
<span></span>
</li> $(document).on('click', 'li', function(){
alert('li click');
}); $(document).on('click', 'span', function(){
alert('li span');
})

  获取当前事件的target目标元素,如果是span标签,就不执行li标签绑定事件的逻辑。

$(document).on('click', 'li', function(e){
if(e.target.nodeName == 'SPAN') {
e.stopPropagation();
return;
}
alert('li click');
});

tap事件是如何实现的

  以下是zepto部分源码,tap是一个自定义事件,监听touchend,并且250ms之内没有触摸操作而被触发

 .on('touchend MSPointerUp pointerup', function(e){

            tapTimeout = setTimeout(function() {

              // trigger universal 'tap' with the option to cancelTouch()
// (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
var event = $.Event('tap')
event.cancelTouch = cancelAll
// [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap
if (touch.el) touch.el.trigger(event) // trigger double tap immediately
if (touch.isDoubleTap) {
if (touch.el) touch.el.trigger('doubleTap')
touch = {}
} // trigger single tap after 250ms of inactivity
else {
touchTimeout = setTimeout(function(){
touchTimeout = null
if (touch.el) touch.el.trigger('singleTap')
touch = {}
}, 250)
}
}, 0)
} else {
touch = {}
}
deltaX = deltaY = 0 })

tap会产生什么问题

  tap会出现目前所谓“点透”的情况,下图是的黑色透明遮罩绑定了tap,提交按钮绑定了click事件,如果在按钮的位置点击遮罩,会同时触发click和tap,

tap的延迟为250毫秒,而click事件的延迟是300毫秒。tap触发隐藏遮罩后,click刚好延迟结束,此时按钮就会被点击。

zepto的touch库做了什么

  zepto touch库通过touchmove,touchstart和touchend,封装了自定义事件:触摸,双击,长按,滑动,方向滑动等。

fastclick解决了什么问题

  fastclick解决了click事件延迟的问题,因为300毫秒的延迟会造成很多问题,在移动端会干扰touch事件。

fastclick核心代码:

FastClick.prototype.onTouchEnd = function(event){
if (!this.needsClick(targetElement)) {
// 则屏蔽原生事件,避免触发两次click
event.preventDefault();
// 触发一次模拟的click
this.sendClick(targetElement, event);
}
}
FastClick.prototype.sendClick = function(targetElement, event) {

  // 创建一个鼠标事件
clickEvent = document.createEvent('MouseEvents');
// 初始化鼠标事件为click事件
clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); // fastclick的内部变量,用来识别click事件是原生还是模拟
clickEvent.forwardedTouchEvent = true; // 在目标元素上触发该鼠标事件,
targetElement.dispatchEvent(clickEvent);

 fastclick会造成某些问题

  造成安卓移动端的video交互事件失效

总结JavaScript事件机制的更多相关文章

  1. 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

    前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...

  2. Javascript事件机制兼容性解决方案

    本文的解决方案可以用于Javascript native对象和宿主对象(dom元素),通过以下的方式来绑定和触发事件: 或者 var input = document.getElementsByTag ...

  3. 【探讨】javascript事件机制底层实现原理

    前言 又到了扯淡时间了,我最近在思考javascript事件机制底层的实现,但是暂时没有勇气去看chrome源码,所以今天我来猜测一把 我们今天来猜一猜,探讨探讨,javascript底层事件机制是如 ...

  4. JavaScript事件机制——细思极恐

    JavaScript事件机制,也有让人深思的东西.在一开始未深入了解,我头脑里有几个问题发出: 1. 自下而上(冒泡)事件怎么写,自上而下(捕获)又是怎么写? 2. 捕获型和冒泡型同时设置,谁生效? ...

  5. 重温javascript事件机制

    以前用过一段时间的jquery感觉太方便,太强大了,各种动画效果,dom事件.创建节点.遍历.控件及UI库,应有尽有:开发文档也很多,网上讨论的问题更是甚多,种种迹象表明jquery是一个出色的jav ...

  6. [解惑]JavaScript事件机制

    群里童鞋问到关于事件传播的一个问题:“事件捕获的时候,阻止冒泡,事件到达目标之后,还会冒泡吗?”. 初学 JS 的童鞋经常会有诸多疑问,我在很多 QQ 群也混了好几年了,耳濡目染也也收获了不少,以后会 ...

  7. javascript事件机制

    ① javascript绑定事件的方式 http://blog.iderzheng.com/dom-javascript-event-binding-comparison/ ② javascript事 ...

  8. 对JavaScript事件机制的一点理解

    JavaScript通过事件机制实现了异步操作,这种异步操作可以使CPU可以在IO任务的等待中被释放出来处理其他任务,等待IO结束再去处理这个任务.这个是一个基本的事件机制. 那么是不是说事件从监听到 ...

  9. JavaScript——事件机制

    事件是将JavaScript脚本与网页联系在一起的主要方式,是JavaScript中最重要的主题之一,深入理解事件的工作机制以及它们对性能的影响至关重要.本文将详细介绍JavaScript的事件机制, ...

随机推荐

  1. DirectX游戏编程(一):创建一个Direct3D程序

    一.环境 Visual Studio 2012,DirectX SDK (June 2010) 二.准备 1.环境变量(如没有配置请添加) 变量名:DXSDK_DIR 变量值:D:\Software\ ...

  2. 关于learntorank http://qiita.com/rockhopper/items/bb3d46f01df5f6499123

    一.数据转换 如何对于训练数据做pairwise的transform,比如你原始数据是要么点击要么不点击,如何对这些样本数据做pairwise的transform? 下面的方法主要是做组合的方法,就是 ...

  3. CF2.D 并查集+背包

    D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...

  4. 新书到手 TRANSACTION PROCESSING:CONCEPTS AND TECHNIQUES

    新书到手 TRANSACTION PROCESSING:CONCEPTS AND TECHNIQUES Jim Gray大神的著作 本文版权归作者所有,未经作者同意不得转载.

  5. Windows系统上的.Net版本和.NETFramework的C#版本

    前言 注:本文内容摘自维基百科,用于在墙内时当作笔记看. WinForm 需要.Net最低版本 2.0 WPF需要的.Net最低版本 3.0 (Win7及之上版本自带) C#版本 版本 语言规格 日期 ...

  6. STOMP协议介绍

    STOMP,Streaming Text Orientated Message Protocol,是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息 ...

  7. 基于OWin的Web服务器Katana发布版本3

    当 ASP.NET 首次在 2002 年发布时,时代有所不同. 那时,Internet 仍处于起步阶段,大约有 5.69 亿用户,每个用户平均每天访问 Internet 的时间为 46 分钟,大约有 ...

  8. 剑指Offer面试题:23.二叉树中和为某一值的路径

    一.题目:二叉树中和为某一值的路径 题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.例如输入下图中二叉树和整数2 ...

  9. 【转】我的技术学习方法 — Anytao

    原文作者:anytao—王涛 他的著作:<你必须知道的.Net> 关于这个问题,也有不少刚刚入行的朋友向我问起.我想可能一千个人就有一千个答案,我不能保证自己的想法适合于所有的人,但是这确 ...

  10. 初试ASP.NET Web API/MVC API(附Demo)

    写在前面 HTTP RESTful 创建Web API 调用Web API 运行截图及Demo下载 ASP.NET Web API是​​一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览 ...