# 2.事件绑定、委托、阻止默认事件和阻止冒泡
# 事件绑定的三种方法
# 一、直接在 html 标签里添加事件。
HTML 元素行间事件(也可以叫 HTMl 事件处理程序)
- 缺点:html 和 js 代码紧密耦合
<input type="button" οnclick="test();"/>
<script>
function test() {
alert("我是行间事件");
}
</script>
2
3
4
5
6
# 二、把一个函数赋值给一个事件处理程序属性。
添加事件的方法,用的比较多的一种方式:把一个函数赋值给一个事件处理程序属性。(这种方式也叫做Dom0 级事件处理程序)
优点:简单而且有跨浏览器的优势 缺点:只能触发一个方法,如果需要同时触发两个方法,只能使用事件监听 而且,onclick,onmousemove 等这些事件在网页中都可以很到的支持,但是在手机上就失效了,在手机上需要通过“事件监听”的方式来实现事件绑定,
<body>
<input id="button1"type="button" value="按钮"/>
<script>
document.getElementById('button1').onclick = function (){
console.log(111);
}
//或者
function abc() {
console.log('abc');
}
document.getElementById('button1').onclick = abc
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
# 三、事件监听:只可以在该元素的事件监听中看到
也叫Dom2 级事件处理程序
<input id="inputBtn" type="button" value="click"/>
<script>
var inputBtn = document.getElementById('inputBtn');
inputBtn.addEventListener('click',showMsg,false);//鼠标单击的时候调用showMes这个函数
function showMsg() {
alert("事件监听");
}
// 移除文档中的事件句柄
document.removeEventListener(inputBtn , showMsg, false)
</script>
2
3
4
5
6
7
8
9
10
11
addEventListener('click',showMsg,false); 有三个参数
第一个代表触发什么事件,注意这里的写法没有 on
第二个参数代表事件发生时调用的事件处理函数
第三个参数是布尔值:true 或者 false
第三个参数是 true:表示在捕获阶段响应事件
第三个参数是 false:表示在冒泡阶段响应事件
2
3
4
5
6
7
8
9
# 委托
选自:JavaScript 事件代理(事件委托) (opens new window)
“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown......)委托给父元素,让父元素担当事件监听的职务。 事件代理的原理是 DOM 元素的事件冒泡。
# 什么是事件冒泡
前面提到事件委托的原理是 DOM 元素的事件冒泡,那么事件冒泡是什么呢?
一个事件触发后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段 如上图所示,事件传播分成三个阶段:
- 捕获阶段:从 window 对象传导到目标节点(上层传到底层)称为“捕获阶段”(capture phase),捕获阶段不会响应任何事件;
- 目标阶段:在目标节点上触发,称为“目标阶段”
- 冒泡阶段:从目标节点传导回 window 对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)。 事件代理即是利用事件冒泡的机制把里层所需要响应的事件绑定到外层;
# 事件委托的优点
# 【1】可以大量节省内存占用,减少事件注册,比如在 ul 上代理所有 li 的 click 事件就非常棒
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
2
3
4
5
6
7
8
如上面代码所示,如果给每个 li 列表项都绑定一个函数,那对内存的消耗是非常大的,因此较好的解决办法就是将 li 元素的点击事件绑定到它的父元素 ul 身上,执行事件的时候再去匹配判断目标元素。
# 【2】可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
# 基本实现
# 【1】JavaScript 原生实现事件委托
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
2
3
4
5
按照传统的做法,需要像下面这样为它们添加 3 个事 件处理程序
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
item1.onclick = function () {
location.href = "http://www.baidu.com";
};
item2.onclick = function () {
document.title = "事件委托";
};
item3.onclick = function () {
alert("hi");
};
2
3
4
5
6
7
8
9
10
11
12
13
此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
document.addEventListener("click", function (event) {
var target = event.target;
switch (target.id) {
case "doSomething":
document.title = "事件委托";
break;
case "goSomewhere":
location.href = "http://www.baidu.com";
break;
case "sayHi":
alert("hi");
break;
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 阻止默认事件
# 1、什么是默认事件
如:a 标签链接跳转 我们有没有办法在 a 点击后让他不跳转的处理呢?这是肯定有的,a 在点击会触发 click 事件,我们只要在回调中加入事件阻止方法就可以阻止跳转发生:
<a href="https://www.baidu.com/" target="_blank" id="skip">
百度
</a>;
var skip = document.getElementById("skip");
skip.onclick = function (event) {
event.preventDefault();
};
2
3
4
5
6
7
8
再次点击百度,还会停留在当前页面,当然除了调用事件对象的阻止方法还可以用下面的处理:
skip.onclick = function (event) {
return false;
};
2
3
# 2、“阻止事件冒泡”和“阻止默认事件”
# 非 IE 浏览器
1.event.stopPropagation()方法 (Propagation 传播)
这是阻止事件的冒泡方法,不让事件向 documen 上蔓延,但是默认事件任然会执行,当你掉用这个方法的时候,如果点击一个连接,这个连接仍然会被打开,
2.event.preventDefault()方法(prevent 防止 default 默认)
这是阻止默认事件的方法,调用此方法是,连接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素;
3.return false ;
这个方法比较暴力,他会同事阻止事件冒泡也会阻止默认事件;写上此代码,连接不会被打开,事件也不会传递到上一层的父元素; 可以理解为 return false 就等于同时调用了 event.stopPropagation()event.preventDefault()
# IE 浏览器
IE 浏览器不支持 event.stopPropagation()event.preventDefault()
1、阻止冒泡(bubble 气泡) e.cancelBubble = true
2、阻止默认事件 e.returnValue = false;