JavaScript绑定事件的三种方式

@(javascript)[JavaScript事件绑定]

JavaScript绑定事件的三种方式

  • 使用内联
  • 使用.onclick的方式
  • 使用事件监听addEventListener的方式

内联

形式:

<input type="button" value="按钮" onclick="alert(1);">

这种方式就是在一个元素上面直接绑定了一个点击onclick事件,此事件为DOM 0级标准。同时,这个事件的优先级是最高的。

使用对象.事件的形式

形式

<input type="button" value="按钮">

<script type="text/javascript">
    var bt = document.getElementsBytagname("input")[0];
    bt.onclick = function(){
        alert(2)
    }
</script>

使用这种形式也是可以给一个DOM元素添加上一个事件。这个也是DOM 0级标准

以上的弊端

以上两种方式都是存在一个弊端的,就是一个元素只能添加一个事件。第一种就不用说了,写在行内就一个属性。至于第二种,有的网友可能会说我可以再写一个,比如:

<input type="button" value="按钮">

<script type="text/javascript">
    var bt = document.getElementsBytagname("input")[0];
    bt.onclick = function(){
        alert(2)
    }
    
    bt.onclick = function(){
        alert(3)
    }
</script>

写是可以这么写。那么我们先来看一看这个写法的意思,这种写法的本质就是在一个对象上添加一个属性,就上面的例子,就是在bt这个对象上添加一个onclick属性。那么,如果在之后的代码中也存在bt.onclcik,只会吧前面的给覆盖了。所以这样的写法也只能添加一个事件。

那么,问题来了。我要给一个元素(DOM对象)添加两个甚至是多个事件,使用什么呢?此时,就需要使用addEventListener的方式来添加事件。

addEventListener

形式:

<input type="button" value="按钮">

<script type="text/javascript">
    var bt = document.getElementsBytagname("input")[0];
    bt.addEventListener("click", function(){
        alert(1)
    })
    bt.addEventListener("click", function(){
        alert(2)
    })
</script>

上面的方式就可以给一个DOM对象绑定一个或者是多个事件。强烈推荐使用这一种绑定事件的方式
使用addEventListener的方式还可以拥有第三个参数。
以下是W3C官网的一个话

image

三个参数:

  1. 事件类型,不需要添加上on
  2. 事件函数
  3. 是否捕获(布尔值),默认是false,即不捕获,那就是冒泡。

那么捕获和冒泡又是什么呢?
下面来看一张图:
这是三个盒子,相互嵌套的关系

<div id="a">
    a
    <div id="b">
        b
        <div id="c">c</div>
    </div>
</div>

那么捕获是什么意思呢?


image

弓箭射过来,没穿过一个盒子,就捕获一次,这个过程就是捕获过程。
而下面的就是冒泡


image

捕获和冒泡会影响到事件的执行顺序

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕获
a.addEventListener("click", function(){
    alert("b-a")
},true)
b.addEventListener("click", function(){
    alert("b-b")
},true)
c.addEventListener("click", function(){
    alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
    alert("m-a")
},false)
b.addEventListener("click", function(){
    alert("m-b")
},false)
c.addEventListener("click", function(){
    alert("m-c")
},false)

上面的代码的执行顺序为:b-a,b-b,b-c,m-c,m-b,m-a。先执行的捕获在是冒泡。得出:同时存在捕获与冒泡时,捕获的优先级是高于冒泡的

下面,我们变一下代码:

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕获
a.addEventListener("click", function(){
    alert("b-a")
},true)
b.addEventListener("click", function(){
    alert("b-b")
}) // 此处不在添加捕获事件,那么就是绑定一个默认的事件
c.addEventListener("click", function(){
    alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
    alert("m-a")
},false)
b.addEventListener("click", function(){
    alert("m-b")
},false)
c.addEventListener("click", function(){
    alert("m-c")
},false)

此时的执行顺序为:b-a,b-c,m-c,b-b,m-b,m-a

再来:

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕获
a.addEventListener("click", function(){
    alert("b-a")
},true)


b.addEventListener("click", function(){
    alert("m-b")
},false) // 把b的冒泡放在这里来了
b.addEventListener("click", function(){
    alert("b-b")
}) // 此处不在添加捕获事件,那么就是绑定一个默认的事件。即冒泡


c.addEventListener("click", function(){
    alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
    alert("m-a")
},false)
c.addEventListener("click", function(){
    alert("m-c")
},false)

此时的执行顺序为:b-a,b-c,m-c,m-b,b-b,m-a
得出,没有捕获的时候谁在前面先执行谁

OK。事件绑定就此结束。下面说说取消事件绑定吧。如果要取消一个使用addEventListener绑定的事件函数,使用removeEventListener可以移除事件。

image

与添加事件一致。不过如果使用这个,最好把这个函数给单离拿出来。

停止传播

使用stopPropagation可以阻止事件的传播。不能使用return false

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕获
a.addEventListener("click", function(){
    alert("b-a")
},true)
b.addEventListener("click", function(){
    alert("b-b")
})
c.addEventListener("click", function(){
    alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
    alert("m-a")
})
b.addEventListener("click", function(){
    alert("m-b")
},false)

// 阻止冒泡
c.addEventListener("click", function(e){
    alert("m-c")
    e.stopPropagation(); // 此处阻止传播
},false)

此时的顺序:b-a,b-c,m-c。不会传递,后面的不会执行了。阻止捕获也是一样,添加之后就不会在继续往下传递了。

这里有涉及到一个阻止事件的默认行为preventDefault或者是前面提到的return false

对于IE下的事件绑定

适用与IE6,7,8
IE的事件与模型与W3C的标准事件相比,主要是以下三点不同:

  1. 绑定事件的函数不同,IE中使用attachEvent()和detachEvent()
  2. 事件必须加上on
  3. IE6模型中,不支持捕获,只支持冒泡
  4. IE中还有毛病,先绑定的事件后发生(准确的说是随机发生)
  5. IE中this指向window

更新与2017年12月2日14:30:05

关于使用addEventListener

给元素添加事件一般使用addEventListener的方式来添加,这样才可以个一个元素添加多个事件。但是由于addEventListener单词太长,容易写错,并且代码压缩的时候不会压缩,所以一般很少直接使用他,而是使用函数把他封装起来使用,避免出错:

function addEvent(ele,type,fn){
    ele.addEventListener(type,function(e){
        fn(e)
    })
}

使用以上的方式可以减少出错率以及方便

关于事件代理(委托)

一般情况下,如果一个元素下存在多个点击事件,代码结构如下:

<ul id="box">
    <li>list-1</li>
    <li>list-2</li>
    <li>list-3</li>
    <li>list-4</li>
</ul>

此时,如果你要给每一个li标签添加一个点击事件,弹出每一个li的索引值,初学者可能会使用for循环的方式来添加:

var oLis  = document.getElementsByTagName("li");

for (var i = 0; i < oLis.length; i++) {
    oLis[i].i = i;
    addEvent(oLis[i],"click",function(e){
        alert(this.i)
    })
}

或者是使用闭包:

var oLis  = document.getElementsByTagName("li");

for (var i = 0; i < oLis.length; i++) {
    (function(i){
        addEvent(oLis[i],"click",function(e){
            alert(i)
        })
    })(i)
}

但是以上两种都不是一个最好的方法,因为你的li的个数可能发生改变,如果是这样的话,可能会出一些问题。那么,此时如果使用事件代理的方式,效果会更好。
事件代理代码:

var oBox = document.getElementById("box");

addEvent(oBox,'click',function(e){
    var target = e.target;
    // 判断点击的是li
    if ( target.nodeName == 'LI' ) {
        alert(target.innerHTML)
    }
})

这样也是可以的,不过此时的addEvent函数点击的时候就需要在fn里面判断点击的是哪一个标签。为了更好的使用addEvent,我们可以改进一下:

function addEvent(ele,type,selector,fn){
    // 如果只有三个参数,那么3,4互换
    if ( fn == null ) {
        fn = selector;
        selector = null
    }
    ele.addEventListener(type,function(e){
        var target;
        if ( selector ) {
            //  代理
            target = e.target;
            if(target.matches(selector)){
                fn.call(target.e)
            }
        } else {
            // 不代理
            fn(e)
        }
    })
}

这时点击li弹出innerHTML就可以这样实现

addEvent(oBox,'click','li',function(e){
    alert(this.innerHTML)
})
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  •   JavaScript 与 HTML 之间的交互是通过事件实现的。   事件,就是文档或浏览器窗口中发生的一些特...
    霜天晓阅读 3,473评论 1 11
  • js之事件机制 1、事件初探 1.1 js事件的概述 JavaScript事件:JavaScript是基于事件驱动...
    道无虚阅读 2,331评论 1 3
  • 事件绑定的方式 给 DOM 元素绑定事件分为两大类:在 html 中直接绑定 和 在 JavaScript 中绑定...
    Bruce_zhuan阅读 1,025评论 0 6
  • 以下文章为转载,对理解JavaScript中的事件处理机制很有帮助,浅显易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy阅读 3,023评论 1 10
  • 我喜欢虚幻的世界 让所有的触角伸张 摆着舒服的姿势 仰望最蓝的天空 在银河里捕捉小星星 用太阳的大脸烤番薯 好开心...
    方堇子阅读 197评论 0 0