dom类型
dom 0 onclick
<script>
var btn=document.getElementById("#btn");
btn.onclick=function(){
alert(hello world!)
}
</script>
dom2 addevent listener
进一步规范后,有了DOM2级事件处理程序,我们可以通过类似如下代码,对一个元素的同一个事件添加多个处理程序
var btn=document.getElementById("#btn");
btn.addEventListener("click",function(){
alert(hello world!)
})
btn.addEventListener("click",function(){
alert(hello world2!)
})
dom3 支持多个事件比如 keyup
实际上,之前我们提到的addEventListener还有第三个参数,可以为true或false.当第三个参数为true时,绑定的是捕获阶段的事件,在捕获阶段,事件是由上到下依次触发的,反之当第三个参数为false时,绑定的是冒泡阶段的事件,在冒泡阶段,事件是由下到上触发的
DOM事件流的三个阶段:
事件捕获阶段
处于目标阶段
事件冒泡阶段


事件流代码 与 自定义事件
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="ev" style="display: inline-block; width: 200px; height: 200px; background: red;">
</div>
<script type="text/javascript">
window.addEventListener('click', function () {
console.log('window on click');
}, true);
document.addEventListener('click', function () {
console.log('document on click');
}, true);
document.documentElement.addEventListener('click', function () {
console.log('html on click');
}, true);
document.getElementById("ev").addEventListener('click', function () {
console.log('ev on click');
}, true);
document.body.addEventListener('click', function () {
console.log('body on click');
}, true);
// event
var event = new Event('ccc');
let ev = document.getElementById('ev');
ev.addEventListener('ccc', function () {
console.log('cccdddd');
});
// custom event, 数据必须定义在 detail 里
var cevent = new CustomEvent('kkkk', {detail: 'ac'});
ev.addEventListener('kkkk', function (e) {
console.log(e.detail);
});
ev.dispatchEvent(event);
ev.dispatchEvent(cevent);
</script>
</body>
</html>
event 对象常见方法
event.preventDefault()
阻止默认跳转行为

<!DOCTYPE html>
<html>
<body>
<a id="myAnchor" href="https://w3schools.com/">Go to W3Schools.com</a>
<p>The preventDefault() method will prevent the link above from following the URL.</p>
<script>
document.getElementById("myAnchor").addEventListener("click", function(event){
event.preventDefault()
});
</script>
</body>
</html>
event.stopPropagation();
阻止冒泡
stopImmediatePropagation();
阻止同一个 dom上的事件的传播,又阻止冒泡
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<body>
<button id="btn">click me to stop propagation</button>
</body>
<script>
const btn = document.querySelector('#btn');
btn.addEventListener('click', event => {
console.log('btn click 1');
});
btn.addEventListener('click', event => {
console.log('btn click 2');
event.stopImmediatePropagation();
});
btn.addEventListener('click', event => {
console.log('btn click 3');
});
document.body.addEventListener('click', () => {
console.log('body click');
});
</script>
</body>
</html>
结果 btn click 1 btn click 2 出现 btn click1, 没有出现btn click3 是因为根据注册顺序执行的
target vs current target
从输出中我们可以看到,event.target指向引起触发事件的元素,而event.currentTarget则是事件绑定的元素,只有被点击的那个目标元素的event.target才会等于event.currentTarget。也就是说,event.currentTarget始终是监听事件者,而event.target是事件的真正发出者。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Example</title>
5 </head>
6 <body>
7 <div id="A">
8 <div id="B">
9 </div>
10 </div>
11 </body>
12 </html>
var a = document.getElementById('A'),
b = document.getElementById('B');
function handler (e) {
console.log(e.target);
console.log(e.currentTarget);
}
a.addEventListener('click', handler, false);
当点击A时:输出:
1 <div id="A">...<div>
2 <div id="A">...<div>
当点击B时:输出:
1 <div id="B"></div>
2 <div id="A">...</div>
复制代码也就是说,currentTarget始终是监听事件者,而target是事件的真正发出者。由于要兼容IE浏览器,所以一般都在冒泡阶段来处理事件,此时target和currentTarget有
vue 时间捕获冒泡
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
ie 事件与chrome 事件的不同
标准事件对象使用 event 的 target 属性获取事件目标。
var btn = document.getElementById('myButton');
btn.addEventListener("click", function(event) {
alert(event.target.id); // myButton
});
IE 事件对象使用 event 的 srcElement 属性获取事件目标。
var btn = document.getElementById("myButton");
btn.attachEvent("onclick", function(event) {
alert(event.srcElement.id); // myButton
});
另外,标准事件对象还有一个 currentTarget 属性,该属性在事件处理函数当中始终与 this 相等,而 target 属性则是指向事件触发的具体目标。
document.body.addEventListener("click", function (event) {
alert(event.currentTarget.id); // myBody
alert(event.target.id); // myButton
alert(this.id); // myBody
});
事件代理
原理是利用冒泡原理,减少对dom 事件的绑定。
那什么样的事件可以用事件委托,什么样的事件不可以用呢?适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。值得注意的是,mouseover和mouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。不适合的就有很多了,举个例子,mousemove,每次都要计算它的位置,非常不好把控,在不如说focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。