一、概述
- 描述:事件本质是一种交互操作,事件通常与函数配合使用,当事件发生时函数才会执行
- 事件是由三部分组成的:事件源 事件类型 事件处理程序
- 事件源:事件被触发的对象–谁
- 事件类型:如何触发 什么事件(比如鼠标点击(onclick)、鼠标经过等等)
- 事件处理程序:通过一个函数赋值的方式完成
作用:
- 1.各元素之间可以借助事件来进行交互
- 2.用户和页面之间也可以通过事件来交互
- 3.后端和页面之间也可以通过事件来交互(减缓服务器压力)
注意:
- 事件通常与函数配合使用,当事件发生时函数才会执行
二、事件传递
- 描述:事件不仅能够和触发者交互,还会在特定的情况下沿着dom tree逐级传递,和dom tree中的各个节点进行交互。而js中的这种机制被称为事件传递机制。
说明:
- 1)触发者:事件第一次在哪个节点发生,那么这个节点就是触发者
- 2)特定的情况:domTree中其他节点也绑定了这个事件
类型:
- **事件冒泡:**事件从最具体的元素开始,沿着DOM树逐级向上依次触发,直至最不具体的元素停止
<div>
<button>点我</button>
</div>
<style>
div {
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<script>
//获得元素
var div = document.querySelector('div');
var but = document.querySelector('button');
but.onclick = function() {
console.log("按钮触发了");
}
div.onclick = function() {
console.log("div触发了");
}
document.body.onclick = function() {
console.log("body触发了");
}
document.documentElement.onclick = function() {
console.log("html触发了");
}
document.onclick = function() {
console.log("document触发了");
}
</script>
当点击button按钮时:
当点击div区域(蓝色部分)时
- 事件捕获:事件从最不具体的元素开始,沿着DOM树逐级向下依次触发,直至达到最具体的元素停止
- DOM0级事件:只支持冒泡
- DOM2级事件:同时涵盖了两个方向,冒泡和捕获
- DOM2级事件先捕获后冒泡,默认在冒泡阶段执行,如果在定义事件时第三个参数传入true,则会在捕获阶段执行函数
<div>
<button>点我</button>
</div>
<style>
div {
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<script>
//获得元素
var div = document.querySelector('div');
var but = document.querySelector('button');
but.addEventListener("click", function(event) {
console.log("but");
}, true)
div.addEventListener("click", function(event) {
console.log("div");
}, true)
document.body.addEventListener("click", function(event) {
console.log("body");
}, true)
</script>
当单击按钮时:
当单击div区域时:
注意:如没有特殊情况,均采用事件冒泡。
示意图:
三、非IE浏览器中的【事件绑定】
1.html事件
- 描述:绑定操作发生在HTML代码中的事件,称为HTML事件
- 语法:on+事件=‘函数();函数();函数();……
注意:
- a.HTML事件采用冒泡机制来处理事件
- b.函数执行的顺序按照绑定事件时函数的顺序为准
- c.绑定多个函数时,函数应当采用分号隔开
HTML事件的缺陷:
- 耦合性太强,修改一处的同时也要修改另一处
- 当函数没有加载成功时,用户去触发事件,则会报错
<div class="div1">div1
<div class="div2" onclick="test3()"> div2</div>
</div>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: blue
}
.div2 {
width: 100px;
height: 100px;
background-color: pink;
margin: 25px auto
}
</style>
<script>
//获得元素
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
function test1() {
console.log("这是第一个函数");
}
function test2() {
console.log("这是第二个函数");
}
function test3() {
console.log("这是第三个函数");
}
</script>
当分别点击 div2 和 div1 区域时:
移除:
- 元素.setAttribute(‘on+事件名’,null);
<script>
//获得元素
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
function test1() {
console.log("这是第一个函数");
}
function test2() {
console.log("这是第二个函数");
}
function test3() {
console.log("这是第三个函数");
}
div1.setAttribute('onclick', null);
</script>
此时当再次单击div1时,div1不会有任何反应!
2.DOM0级事件
- 描述:在js脚本中,直接通过【on+事件名】方式绑定的事件称为是DOM0级事件
- 语法:元素.on+事件名 = function(){需要执行的语句;}
注意:
- (1)dom0方式绑定的事件均为冒泡事件
- (2)dom0方式一个节点,只能绑定一个事件
- (3) 如果同时绑定多个触发函数,则以最后一个为准
弊端:一次只能绑定一个触发函数。
<style>
.div1 {
width: 200px;
height: 200px;
background-color: blue
}
.div2 {
width: 100px;
height: 100px;
background-color: pink;
margin: 25px auto
}
</style>
<div class="div1">div1
<div class="div2"> div2</div>
</div>
<script>
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
div1.onclick = function() {
console.log("div1被点击了1次");
}
div2.onclick = function() {
console.log("div2被点击了1次");
}
div2.onclick = function() {
console.log("div2被点击了2次");
//div2.onclick = null;
}
</script>
当点击div1时:
当点击div2时
移除: 元素. on+事件名=null;
(移除点击事件,不是移除绑定的函数)
<script>
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
div1.onclick = function() {
console.log("div1被点击了1次");
}
div2.onclick = function() {
console.log("div2被点击了1次");
}
div2.onclick = function() {
console.log("div2被点击了2次");
//当放在函数里面时,点击事件会被触发一次,当第二次
//再次点击时将不再有任何反应
div2.onclick = null;
}
//当放在函数外面时,移除的将是整个onclick点击事件,
//因此当你点击对应的区域时则不会被触发
// div2.onclick = null;
</script>
当移除点击事件放在函数里时:
第一次点击div2区域:
第二次点击div2区域:
当移除点击事件放在函数外时:
此时当你点击div2区域时,该区域的绑定事件不会触发
3.DOM2级事件
- 描述:在js脚本中,通过addEventListener函数绑定的事件称为是DOM2级事件
- 语法:元素.addEventListener(type,listener,useCapture)
参数:
- type:事件类型。【没有on!没有on!没有on!】
- listener:监听函数,绑定的函数
- useCapture:是否使用捕获机制。如果不写,默认值为false;false:冒泡机制;true:捕获机制
<style>
.div1 {
width: 200px;
height: 200px;
background-color: blue
}
.div2 {
width: 100px;
height: 100px;
background-color: pink;
margin: 25px auto
}
</style>
<div class="div1">div1
<div class="div2"> div2</div>
</div>
<script>
// 获得元素
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
function fun() {
console.log("这是dom2事件函数div2一次");
}
div2.addEventListener('click', fun, true);
div2.addEventListener('click', function() {
console.log("这是dom2事件函数div22次");
}, true)
</script>
注意:
- a. DOM2级事件可以绑定多个函数,执行顺序按照函数书写的顺序
- b. DOM2级事件中如果绑定函数为【匿名函数】则无法删除。能够删除的只能是外部函数。
<script>
// 获得元素
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
function fun() {
console.log("这是dom2事件函数div2一次");
}
div2.addEventListener('click', fun, true);
//div2.removeEventListener('click', fun, true);
//匿名函数
div2.addEventListener('click', function() {
console.log("这是dom2事件函数div22次");
}, true)
div2.removeEventListener('click', function() {
console.log("这是dom2事件函数div22次");
}, true);
</script>
移除:
- 语法: node.removeEventListener(type,外部函数名,useCapture)
<script>
// 获得元素
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
function fun() {
console.log("这是dom2事件函数div2一次");
}
div2.addEventListener('click', fun, true);
div2.addEventListener('click', function() {
console.log("这是dom2事件函数div22次");
}, true)
div2.removeEventListener('click',fun,true);
</script>
四、IE浏览器中的【事件绑定】
- IE中的事件绑定支持HTML事件以及DOM0级事件,唯独不支持DOM2级事件
- js脚本中,通过attachEvent函数绑定事件
- 语法:元素.attachEvent(type,listener)
参数:
- type:事件类型。【有on!有on!有on!】
- listener:监听函数,绑定的函数
注意:如果绑定多个函数,按照函数书写的倒叙执行
1.HTML事件
<div class="div1" onclick="test1()">div1
<div class="div2" onclick="test2()"> div2</div>
</div>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: blue
}
.div2 {
width: 100px;
height: 100px;
background-color: pink;
margin: 25px auto
}
</style>
<script>
function test1() {
console.log("这是div1");
}
function test2() {
console.log("这是div2");
}
</script>
当点击div2区域时:
当点击div1区域时:
2.DOM0级事件
<div class="div1">div1
<div class="div2"> div2</div>
</div>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: blue
}
.div2 {
width: 100px;
height: 100px;
background-color: pink;
margin: 25px auto
}
</style>
<script>
document.querySelector('.div1').onclick = function() {
console.log("这是div1第一次");
}
document.querySelector('.div2').onclick = function() {
console.log("这是div2");
}
</script>
当点击div1区域时:
当点击div2区域时:
3.DOM2级事件
- 语法;元素.attachEvent(type,listener)
参数:
- type:事件类型。【有on!有on!有on!】
- listener:监听函数,绑定的函数
注意:如果绑定多个函数,按照函数书写的倒叙执行
<div class="div1">div1
<div class="div2"> div2</div>
</div>
<style>
.div1 {
width: 200px;
height: 200px;
background-color: blue
}
.div2 {
width: 100px;
height: 100px;
background-color: pink;
margin: 25px auto
}
</style>
<script>
document.querySelector('.div1').attachEvent('onclick', fun);
function fun() {
console.log("这是div1一次");
}
</script>
<script>
document.querySelector('.div1').attachEvent('onclick', function() {
console.log("这是div1 1次");
});
document.querySelector('.div1').attachEvent('onclick', function() {
console.log("这是div1 2次");
});
</script>
移除:元素.detachEvent(type,listener)
<script>
document.querySelector('.div1').attachEvent('onclick', fun);
function fun() {
console.log("这是div1一次");
document.querySelector('.div1').detachEvent('onclick', fun);
}
</script>
当第一次点击div1区域时:
当再次点击div1区域时将无任何反应
五、解决浏览器事件绑定兼容性问题
思路:
- 绑定事件:如果能使用addEventListener方法绑定的,就采用本方法;否则采用attachEvent方法
- 解绑事件:如果能采用addEventListener方法绑定的,就采用removeEventListener方法解绑;否则就采用detachEvent方法解绑
语法:
<script>
function addEvent(ele){
if(如果为非IE){
就执行addEventListener
}else{
执行attachEvent
}
}
addEvent();
</script>
具体用法如下:
<div style="width: 200px;height: 200px;background-color: pink"></div>
<script>
var div = document.querySelector('div');
//采用封装,封装成一个对象
var superEvent = {
add: function(ele, type, func) {
if (ele.addEventListener) {
ele.addEventListener(type, func);
} else {
ele.attachEvent('on' + type, func);
}
},
remove: function(ele, type, func) {
if (ele.removeEventListener) {
ele.removeEventListener();
} else {
ele.detachEvent();
}
}
}
function show() {
console.log("这是一个div执行函数");
}
superEvent.add(div, 'click', show);
//superEvent.remove(div, 'click', show);
</script>
非IE下:
IE下:
六、鼠标事件
说明:
- a.dom0级可以给同一个元素绑顶多个不同类型的事件
- b.事件互相之间互不影响
- c.默认是冒泡事件
语法:元素.on+鼠标事件名称 = 调用函数
1.单击事件 onclick
鼠标左键单击事件,当你的鼠标在某个标签上进行点击动作,就会触发该事件
下面是该事件的两种写法:
<div id="div" onclick="fun1()">hahah</div>
<div id="div2" style="width:200px;height: 200px;background-color: pink"></div>
<script>
// 方式1
var fun1=()=>{
console.log("发生点击");
}
// 方式2(推荐)
// 获得元素
var div = document.querySelector('div2');
div.onclick = function() {
alert('单击有效');
}
</script>
当鼠标单击div区域后:
总结:
- 在开发过程中,推荐使用第二种(元素.onclick),因为这种方式更利于维护
- 同时也可以更方便的给新创建出的标签添加事件
- 第一种方式如果要获取标签对象本身,需要在绑定函数时传入this实参;第二种方式通过对象绑定的事件,在函数中可以直接使用this关键字,表示的就是标签对象自己
- 第一种方式在函数中的this表示的window对象,第二种方式如果通过箭头函数来绑定的this也代表window
2.双击事件 ondblclick
鼠标左键双击事件,当你的鼠标在某个标签上快速进行连续两次点击动作,就会触发该事件
<div style="width:200px;height: 200px;background-color: pink"></div>
<script>
// 获得元素
var div = document.querySelector('div');
div.ondblclick = function() {
console.log('双击666');
}
document.body.ondblclick = function() {
console.log("双击body有效");
}
</script>
当鼠标双击div区域后:
当鼠标双击空白区域后:
3.鼠标按下时事件 onmousedown
鼠标按键按下事件,当按下任意一个鼠标按键时,会触发该事件
<div style="width:200px;height: 200px;background-color: pink"></div>
<script>
// 获得元素
var div = document.querySelector('div');
div.onmousedown = function() {
div.style.backgroundColor = 'blue';
}
</script>
当在div区域按下鼠标后:
4.鼠标抬起时事件 onmouseup
鼠标按键弹起事件,当鼠标按键在按下以后再弹起会触发该事件
<div style="width:200px;height: 200px;background-color: pink"></div>
<script>
// 获得元素
var div = document.querySelector('div');
div.onmousedown = function() {
div.style.backgroundColor = 'blue';
}
div.onmouseup = function() {
div.style.backgroundColor = 'orange';
}
</script>
5.鼠标移动时事件 onmousemove
当鼠标在标签上移动时,触发该事件
<div style="width:200px;height: 200px;background-color: pink"></div>
<script>
// 获得元素
var div = document.querySelector('div');
div.onmousemove = function() {
//event对象,仅在函数内部使用,表示事件本身
//clientX clientY ,表示鼠标在视口中的坐标
var x = event.clientX;
var y = event.clientY;
console.log('(x,y):(' + x + ',' + y + ')');
}
</script>
当鼠标在div区域内移动时:
6.鼠标移入移除事件
移入移除不冒泡事件 mouseenter mouseleave
mouseenter :鼠标指向事件,当鼠标第一次移动到这个标签上时触发该事件,而且当我们从该标签内部移动到这个标签的子标签之上时,不会触发该事件
mouseleave:鼠标移出事件,当鼠标从某个标签上离开时触发该事件,如果我们从该标签进入自己的子标签区域不会触发该事件,从子标签区域离开也不会触发该事件
<div class="div1">
<div class="div2"></div>
</div>
<style>
.div1 {
width: 300px;
height: 300px;
background-color: aqua;
}
.div2 {
width: 200px;
height: 200px;
background-color: orange;
}
</style>
<script>
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
div2.addEventListener('mouseenter', function() {
console.log('鼠标进入div2区域');
})
div1.addEventListener('mouseenter', function() {
console.log('鼠标进入div1区域');
})
div2.addEventListener('mouseleave', function() {
console.log('鼠标移出div2区域');
})
div1.addEventListener('mouseleave', function() {
console.log('鼠标移出div1区域');
})
</script>
当鼠标进入和移除div1区域时:
当鼠标进入和移除div2区域时:
移入移除冒泡事件 mouseover mouseout
mouseover:鼠标指向事件,当鼠标第一次移动到这个标签上时触发该事件,而且当我们从该标签内部移动到这个标签的子标签之上时,依然会触发这个事件
mouseout:鼠标移出事件,当鼠标从某个标签上离开时触发该事件,而且如果我们从该标签进入自己的子标签区域也会触发该事件,从标签区域离开也会触发该事件
<div class="div1">
<div class="div2"></div>
</div>
<style>
.div1 {
width: 300px;
height: 300px;
background-color: aqua;
}
.div2 {
width: 200px;
height: 200px;
background-color: orange;
}
</style>
<script>
var div1 = document.querySelector('.div1');
var div2 = document.querySelector('.div2');
//冒泡事件
div2.addEventListener('mouseover', function() {
console.log('鼠标进入div2区域');
})
div1.addEventListener('mouseover', function() {
console.log('鼠标进入div1区域');
})
div2.addEventListener('mouseout', function() {
console.log('鼠标移出div2区域');
})
div1.addEventListener('mouseout', function() {
console.log('鼠标移出div1区域');
})
</script>
当鼠标移入移除div1区域时:
当鼠标移入移除div2区域时:
总结:
- 1.鼠标的基本事件默认采用冒泡传递
- 2.可以给一个元素添加多个不同的鼠标事件,不同的鼠标事件之间互不影响
- 3.mouseenter和mouseleave两个事件不冒泡触发(推荐使用)