一、事件
跟用户交互时,dom结构发不发生改变,此时就用到事件了。
事件是当用户对浏览器进行点击某个地方都可能触发任何一个事件,如用户鼠标单击时、 鼠标移动到元素上。
二、事件流
1.事件冒泡模型
事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素,也就是说
从里向外
2.事件捕获模型
从外向里
3.DOM事件流模型
先捕获,在冒泡
三、使用方式
DOM0
事件处理程序
也称事件侦听器,当用户或浏览器自身执行了某个事件,而响应某个事件就叫事件处理程序
1.js指定事件
<input id="btnClick" type="button" value="Click Here" />
<script type="text/javascript">
var btnClick = document.getElementById('btnClick');
btnClick.onclick = function showMessage() {//元素.事件=事件处理函数 () //onclick也可是其他事件名称
alert(this.id);
};
</script>
//如果是多个相同事件注册用这种方式,最后一个执行,之前的被覆盖了
(2)对一个元素绑定多个事件函数 (注:会发生覆盖)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<button id="btn">click me</button>
</body>
</html>
<script>
var btn = document.querySelector('#btn')
//#事件01
btn.onclick = function(){
console.log(this)
console.log(this.innerText)
}
//#事件02
btn.onclick = function(){
console.log('hello world')
}
</script>
事件01被覆盖
DOM2事件处理程序
DOM2级事件定义了两个方法用于处理指定和删除事件处理程序的操作:
- addEventListener
- removeEventListener
所有的DOM节点都包含这两个方法,并且它们都接受三个参数:
1.事件类型
2.事件处理方法
3.布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理
绑定事件
addEventListener
为同一个元素绑定多个相同的事件:
绑定事件的两个属性:
- 对象.addEventListener("事件类型",事件处理函数,false);--谷歌和火狐支持,IE8不支持
- 对象.attachEvent("有on的事件类型(如:onclick)",事件处理函数)--谷歌不支持,火狐不支持,IE8支持
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<input type="button" value="按钮" id="btn"/>
</body>
<script>
如:
第一种:
//为按钮绑定点击事件
//参数1:事件的类型----事件的名字,没有on
//参数2:事件处理函数----函数(命名函数,匿名函数)
//参数3:布尔类型----默认是事件冒泡(false),事件捕获(true)
function btn$(id) {
return document.getElementById(id);
}
btn$("btn").addEventListener("click",function () {
console.log("呵呵");
},false);//默认是false,可写可不写
btn$("btn").addEventListener("click",function () {
console.log("哈哈");
},false);
btn$("btn").addEventListener("click",function () {
console.log("哦哦");
},false);
btn$("btn").addEventListener("click",function () {
console.log("谔谔");
},false);
第二种:
//参数1:事件类型---事件名字,有on
//参数2:事件处理函数---函数(命名函数,匿名函数)
function btn$(id) {
return document.getElementById(id);
}
btn$("btn").attachEvent("onclick",function () {
console.log("谔谔");
});
btn$("btn").attachEvent("onclick",function () {
console.log("哦哦");
});
btn$("btn").attachEvent("onclick",function () {
console.log("哈哈");
});
//JavaScript指定事件的事件是:onclick,DOM2事件处理程序的事件是:click
</script>
没有发生覆盖
没有发生覆盖
总结:总结绑定事件的区别:
- addEventListener();
- attachEvent()
- 相同点: 都可以为元素绑定事件
- 不同点:
- 1.方法名不一样
- 2.参数个数不一样addEventListener三个参数,attachEvent两个参数
- 3.addEventListener 谷歌,火狐,IE11支持,IE8不支持
- attachEvent 谷歌火狐不支持,IE11不支持,IE8支持
- 4.this不同,addEventListener 中的this是当前绑定事件的对象
- attachEvent中的this是window
- 5.addEventListener中事件的类型(事件的名字)没有on
- attachEvent中的事件的类型(事件的名字)有on
为按钮绑定多个点击事件
function btn$(id) {
return document.getElementById(id);
}
btn$("btn").addEventListener("click",function () {
console.log(this);
},false);
btn$("btn").attachEvent("onclick",function () {
console.log(this);
});
如何解绑事件(一般情况下不做)
removeEventListener
removeEventListener不能使用匿名函数(无法获知要移除谁)
如:
<script type="text/javascript">
var btnClick = document.getElementById('btnClick');
var handler=function() {
alert(this.id);
}
btnClick.removeEventListener('click', handler, false);
</script>
四、演示
冒泡阶段与阻止冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
#dv1{
width: 300px;
height: 200px;
border: 1px solid ;
}
#dv2{
width: 250px;
height: 150px;
border: 1px solid ;
}
#dv3{
width: 200px;
height: 100px;
border: 1px solid ;
}
</style>
</head>
<body>
<div id="dv1">a
<div id="dv2">b
<div id="dv3">c</div>
</div>
</div>
<script>
function $(id) {
return document.getElementById(id);
}
//事件冒泡-->阻止事件冒泡,
//如何阻止事件冒泡: window.event.cancelBubble=true; IE特有的,谷歌支持,火狐不支持
//.preventDefault() //取消时间默认行为。
// .stopPropagation(); 谷歌和火狐支持。 //描述:取消事件进一步捕获或冒泡
$("dv1").onclick=function () {
console.log(this.id);
};
$("dv2").onclick=function () {
console.log(this.id);
//window.event.cancelBubble=true; //阻止事件冒泡
};
//事件处理参数对象
$("dv3").onclick=function (e) { //加参数e
console.log(this.id);
e.stopPropagation(); //阻止事件冒泡 //参数e
console.log();
};
</script>
</body>
</html>
从里到外
- 事件冒泡:多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的元素的事件触发了,外面的元素的该事件自动的触发了.
整个事件就是从里到外
捕获阶段
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
#dv1 {
width: 300px;
height: 200px;
border: 1px solid ;
}
#dv2 {
width: 250px;
height: 150px;
border: 1px solid ;
}
#dv3 {
width: 200px;
height: 100px;
border: 1px solid ;
}
</style>
</head>
<body>
<div id="dv1">a
<div id="dv2">b
<div id="dv3">c</div>
</div>
</div>
<script>
function btn$(id) {
return document.getElementById(id);
}
//捕获阶段:是从里向外
//同时注册点击事件
var objs = [btn$("dv3"),btn$("dv2"), btn$("dv1")];
//遍历注册事件
objs.forEach(function (ele) {
//为每个元素绑定事件
ele.addEventListener("click", function () {
console.log(this.id);
}, true);//捕获阶段是true,冒泡阶段是false
});
//该属性在事件参数对象中存在
</script>
</body>
</html>
从里向外
事件有三个阶段:
* (Dom2传播机制)三个阶段:
* 1.事件捕获阶段 :从外向内
* 2.事件目标阶段 :最开始选择的那个
* 3.事件冒泡阶段 : 从里向外
*
* 为元素绑定事件:
* addEventListener("没有on的事件类型",事件处理函数,控制事件阶段的)
* 事件触发的过程中,可能会出现事件冒泡的效果,为了阻止事件冒泡--->
* window.event.cancelBubble=true;谷歌,IE8支持,火狐不支持
* window.event就是一个对象,是IE中的标准
* e.stopPropagation();阻止事件冒泡---->谷歌和火狐支持
* window.event和e都是事件参数对象,一个是IE的标准,一个是火狐的标准
* 事件参数e在IE8的浏览器中是不存在,此时用window.event来代替
* addEventListener中第三个参数是控制事件阶段的
* 事件的阶段有三个:
* 通过e.eventPhase这个属性可以知道当前的事件是什么阶段的
* 如果这个属性的值是:
* 1---->捕获阶段
* 2---->目标阶段
* 3---->冒泡
* 一般默认都是冒泡阶段,很少用捕获阶段
* 冒泡阶段:从里向外
* 捕获阶段:从外向内
区别:
onlick与addEventListener的区别?
1.onclick事件在同一时间只能指向唯一对象
2.addEventListener给一个事件注册多个listener
3.addEventListener对任何DOM都是有效的,而onclick仅限于HTML
4.addEventListener可以控制listener的触发阶段,(捕获/冒泡)。对于多个相同的事件处理器,不会重复触发,不需要手动使用removeEventListener清除
5.IE9使用attachEvent和detachEvent
attachEvent与addEventListener的区别
参数个数不相同:
-
addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(默认冒泡)
-
第一个参数意义不同:
addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload) -
事件处理程序的作用域不相同:
addEventListener的作用域是元素本身,this是指的触发元素;而attachEvent事件处理程序会在全局变量内运行,this是window,所以刚才例子才会返回undefined,而不是元素id -
为一个事件添加多个事件处理程序时执行顺序不同:
addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器。
自定义事件
var EventCenter = {
on: function(type, handler){
document.addEventListener(type, handler)
},
fire: function(type, data){
return document.dispatchEvent(new CustomEvent(type, {
detail: data
}))
}
}
EventCenter.on('hello', function(e){
console.log(e.detail)
})
EventCenter.fire('hello', '你好')
网友评论