1 事件绑定:事件与函数绑定以及怎么取消绑定

1.1 元素.onclick这种形式,如下:

         <div id="div1">aaa</div>

         <script type="text/javascript">
var oDiv1 = document.getElementById('div1');
oDiv1.onclick = function(){
alert(this.innerHTML); //将会弹出aaa
}
</script>

这种绑定不存在什么兼容性问题,但是如果想绑定2个事件,就麻烦了。上面的js代码改成如下:

             var oDiv1 = document.getElementById('div1');
oDiv1.onclick = function(){
alert(this.innerHTML); //将会弹出aaa
}
oDiv1.onclick = function(){
alert(this.nodeType);
}

我们给oDiv1后面又绑定了onclick,前面的那个alert(this.innerHTML)就会失效。

这种方式绑定了,后面的代码需要取消这个绑定,哪怎么取消呢

 //取消刚才的绑定
oDiv1.onclick = null;

当然,这里只是很简单的两个函数例子,可以很容易将2个onclick合并,但是如果是多人合作,代码多,结构复杂,还是看看其他的事件和函数绑定的方式吧。

1.2 元素.attachEvent 和 元素.addEventListener进行事件和函数绑定和取消,如下:

这种方式存在浏览器兼容性问题

/* 总结
ie6/7/8 :obj.attachEvent(事件名称,事件函数);
1.没有捕获(事件捕获在后面讲,是和冒泡相反的,IE不支持)
2.事件名称带有on,如这里是onclick
3.事件函数执行的顺序是反着的,后绑定的那个函数先执行
4.事件函数中this指向window,这不是本意,带来了不方便
标准浏览器及高版本IE:obj.addEventListener(事件名称,事件函数,是否捕获);
1.有捕获
2.事件名称不带on
3.事件执行的顺序是正常的
4.this触发该事件的对象
*/

上面的代码继续改,如下:

下面的代码只能在IE6.7.8.9下运行,但是ie9也有addEventListener方法,就是IE9下attachEvent和addEventListener都行

         <div id="div1">aaa</div>

         <script type="text/javascript">
var oDiv1 = document.getElementById('div1');
//改的是这里,事件和函数进行绑定
oDiv1.attachEvent('onclick',function(){
//这里的this变成了window,也不能用this.innerHTML了
alert(oDiv1.innerHTML);
});
oDiv1.attachEvent('onclick',function(){
alert(oDiv1.nodeType);
});
</script>

再看看标准浏览器,如谷歌火狐浏览下怎么写

         <div id="div1">aaa</div>

         <script type="text/javascript">
var oDiv1 = document.getElementById('div1');
//改的是这里,事件和函数进行绑定,IE.6.7.8不支持addEventListener
oDiv1.addEventListener('click',function(){
//在标准浏览器下,this还是只oDiv1
alert(this.innerHTML);
});//addEventListener第三个参数没写,默认:冒泡
oDiv1.addEventListener('click',function(){
alert(this.nodeType);
});
</script>

存在兼容性问题,我们封装一个函数进行事件绑定操作

         <div id="div1">aaa</div>

         <script type="text/javascript">
var oDiv1 = document.getElementById('div1'); //改的是这里,封装了一个bind函数来解决
function bind(obj,evname,fn){
if(obj.addEventListener){ //IE9+、谷歌、火狐等
obj.addEventListener(evname,fn);
}else{//IE6.7.8,虽然IE9也支持attachEvent,但是IE9用上面的addEventListener了
obj.attachEvent('on'+evname,function(){
fn.call(obj);
});
}
} //使用
bind(oDiv1, 'click', function(){
alert(this.innerHTML);
});
bind(oDiv1, 'click', function(){
alert(this.nodeType);
});
</script>

那怎么取消掉这种方式绑定呢?

/*
老ie : obj.detachEvent(事件名称,事件函数);
标准 : obj.removeEventListener(事件名称,事件函数,是否捕获);
*/
/** 上面事件绑定的时候,我没有给函数命名,是个匿名函数。那匿名函数看着是一样的代码,确是不同的对象,就没有办法取消的了。 */ oDiv1.addEventListener('click', fn1, true);
// 绑定的时候是true,取消的时候,最后那个参数也需要为true,为false则取消不掉
// 下面fn1改为fn2不报错,虽然document没有绑定fn2,但是改为fn3就不行了,报错:不存在fn3这个函数
oDiv1.removeEventListener('click', fn1, true);
            var oDiv1 = document.getElementById('div1');

            oDiv1.addEventListener('click',function(){
alert(this.innerHTML);
});
//取消不了,因为匿名函数没有抓手,得用有名字的函数
oDiv1.removeEventListener('click',function(){
alert(this.innerHTML);
});

而上面这个换成下面这样就起效果。

            var oDiv1 = document.getElementById('div1');

            oDiv1.addEventListener('click',fn1});
//这样点击就没有效果,因为取消掉了
oDiv1.removeEventListener('click',fn1); function fn1(){
alert(this.innerHTML);
}

2. 事件冒泡和取消冒泡

2.1 事件冒泡

比如:div1里面有div2,div2里又有div3。那么当点击div3时,系统会认为div2也点了,div1也点了,body也点了,document也点了,一直到window。一层一层往外冒泡。具体内容如下:

     <style>
div {padding: 40px;}
#div1 {background:red}
#div2 {background:green}
#div3 {background:blue; position: absolute; top: 300px;}
</style>
<div id="div1">
<div id="div2">
<div id="div3"></div>
</div>
</div>
<script>
window.onload = function() { //事件冒泡 : 当一个元素接收到事件的时候,会把他接收到的所有传播给他的父级,一直到顶层window.事件冒泡机制
/*
实例来说:
下面的例子,从html中来看,div3是div2的子元素,div2又是div1的子元素,div1是body的子元素
当div3发生事件的时候(这里是onclick),浏览器会认为div2也发生了该事件,div1也发生了该事件
就是事件从子级朝父级冒泡
同时,注意,div3加上绝对定位,视觉上在div1中也不行,点击div3,div1还是会认为被点击了 */ var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
var oDiv3 = document.getElementById('div3'); function fn1() {
alert(this.id);
} //事件函数绑定
oDiv1.onclick = fn1; //告诉div1,如果他接收到了一个点击事件,那么他就去执行fn1
oDiv2.onclick = fn1;
oDiv3.onclick = fn1; }
</script>

那有个问题,在不知道事件冒泡这个事情的时候,也正常用,没出什么问题呀?

答:因为大多数时候,子级点击发生事件就是我们最终的效果,会传到父级身上产生事件,但是父级没绑定函数,也就没有反应,我们也就感觉不到干嘛要学到用到这一块的东西。但是,子级和父级产生冲突的时候,就需要了解原因,取消冒泡了。

子级和父级同一事件冲突举例:

点击某按钮,希望弹出一个div层,而点击页面中任何除去div层一部分,希望div层隐藏。这里,点击按钮和div层都会冒泡到document,就等同于告诉document,点击后弹出div层,而后面点击页面中任何一部分,又希望隐藏div层,document接到完全矛盾的命令,怎么办?只能是点击按钮和div层的时候,取消冒泡,这样,document就不觉得自己被点击了。怎么取消冒泡?如下:

2.2 取消冒泡:事件绑定函数中加上ev.cancelBubble = true;

上面的代码中,fn1修改下就可以了,如下:

             function fn1(ev) {
var ev = ev || window.event;
ev.cancelBubble = true;
alert(this.id);
}

fn1更换过后,点击div3时,由原来的弹出3次,分别是div3,div2,div1,变成了弹出1次,div3,为何?因为取消冒泡了,div2和div1不认为自己被点击了,也就不调用函数了,也就不弹了。

3 事件捕获

3.1 事件捕获

事件捕获是一个和事件冒泡反着的过程。

冒泡是:点了儿子,儿子觉得被点了(如果绑定了函数,函数执行),然后老子也觉得被点了(如果绑定了函数,函数执行)。

捕获是:点了儿子,老子先觉得被点了(如果绑定了函数,函数执行),然后儿子也觉得被点了(如果绑定了函数,函数执行)。

顺序不同,老旧的IE浏览器没有事件捕获的概念,只有冒泡。元素.onclick这种形式的绑定时,就是事件冒泡。

在火狐,谷歌,IE9+浏览器下:

//第三个参数,默认false,也就是冒泡。如果第三个参数为true,则为事件捕获
obj.removeEventListener(事件名称,事件函数,是否捕获);

3.2 取消捕获

我认为捕获没有取消的概念,

事件冒泡时候冲突是这样的。子级点击要往东,父级点击要往西。点击子级的时候,往东,但是父级认为自己也点击了,结果是往西。而点击父级非子级区域时,还是往西。于是矛盾了,只能往西,实现不了往东。

事件是捕获的话,点击,父级要往西,子级要往东,结局:往东。而点击父级的非子级区域时候,往西。往东往西都可以实现。

所以,捕获没有向冒泡那样,还需要取消冒泡,这个概念。这地方是我自己的理解,不一定到位,暂时存疑吧!

JS中事件绑定函数,事件捕获,事件冒泡的更多相关文章

  1. js事件绑定函数

    js中事件绑定方法大致有三种: 1.在DOM元素中绑定 <input onclick="alert('在DOM中绑定')" type="button" v ...

  2. JS+Zero Clipboard swf复制到剪贴板 兼容浏览器(bind事件绑定函数)

    转自http://www.ipmtea.net/css_ie_firefox/201107/07_499.html 1.ZeroClipboard其实是国外的一个js类库,源码结构如: var Zer ...

  3. 兼容IE9以下和非IE浏览器的原生js事件绑定函数

    事件绑定函数的demo如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "htt ...

  4. jQuery 事件绑定 和 JavaScript 原生事件绑定

    总结一下:jQuery 事件绑定 和 JavaScript 原生事件绑定 及 区别 jQuery 事件绑定 jQuery 中提供了四种事件监听绑定方式,分别是 bind.live.delegate.o ...

  5. underscore.js中的节流函数debounce及trottle

    函数节流   throttle and debounce的相关总结及想法 一开始函数节流的使用场景是:放止一个按钮多次点击多次触发一个功能函数,所以做了一个clearTimeout setTimeou ...

  6. JS中的回调函数实例浅析

    本文实例讲述了JS中的回调函数.分享给大家供大家参考,具体如下: 在说回调函数之前,不妨先看一段代码,相信有点js基础的同学都能明白他的含义: ? 1 2 3 document.getElementB ...

  7. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  8. js中如何在一个函数里面执行另一个函数

    1.js中如何在函数a里面执行函数b function a(参数c){ b(); } function b(参数c){ } 方法2: <script type="text/javasc ...

  9. JavaScript -- 时光流逝(七):js中的全局函数

    JavaScript -- 知识点回顾篇(七):js中的全局函数 全局函数可用于所有内建的 JavaScript 对象. (1) encodeURI():把字符串编码为 URI. <script ...

随机推荐

  1. mysql的学习笔记(一)

    前言 开发中经常用mysql和SQL server交替使用,自己都产生知识的混乱.在这里重新整理下mysql的知识,也是梳理自己知识点,因为是学习笔记,所以并不会使用到图形化管理工具.mysql的安装 ...

  2. 1.1专题介绍「深入浅出ASP.NET Core系列」

    大家好,我是IT人张飞洪,专注于.NET平台十年有余. 工作之余喜欢阅读和写作,学习的内容包括数据结构/算法.网络技术.Linux系统原理.数据库技术原理,设计模式.前沿架构.微服务.容器技术等等…… ...

  3. 2.3Options建立配置和实体的映射「深入浅出ASP.NET Core系列」

    希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. Startup.cs中创建MVC中间件 关键代码:services.AddMvc();app.UseMvcWith ...

  4. FeignClient注解及参数

    一.FeignClient注解 FeignClient注解被@Target(ElementType.TYPE)修饰,表示FeignClient注解的作用目标在接口上 1 2 3 4 5 @FeignC ...

  5. oracle学习笔记(三) DCL 数据控制语言与 DDL 数据定义语言

    DCL 数据控制语言 Data control language 之前说过的授权和收权利语句 grant, revoke DDL 数据定义语言 Data define language create ...

  6. 由于服务主机:DCOM服务进程占用过多CPU,导致系统卡死

    最近在使用电脑的时候,总是出现电脑死机,而且鼠标也是经常卡在那里不动了,开始以为是鼠标的问题,还换了个鼠标(飙泪中),这还是一个血的教训啊!!!之后打开任务管理器发现CPU占用已经达到100%,而且一 ...

  7. 前端入门20-JavaScript进阶之异步回调的执行时机

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  8. Vue开发插件

    (一)Vue.js的插件应该有一个公开方法:install. 这个方法的第一个参数是Vue构造器,第二个参数是一个可选的选项对象,一般是如下操作: MyPlugin.install = functio ...

  9. 《JavaScript高级程序设计》笔记:HTML5脚本编程(16)

    跨文档消息传递 跨文档消息传递(cross-document messaging),有时候简称为XDM,指的是在来自不同域的页面间传递消息.例如,www.wrox.com域中的页面与位于一个内嵌框架中 ...

  10. 第七课 路径与列表 html5学习2

    1.路径 一.相对路径1.同级路径2.下级路径 /3.上级路径 ../上一级路径 ../../上两级二.绝对路径 2.列表 列表特点;整齐.整洁.有序 一.无序列表语法格式<ul> < ...