HTML DOM 允许 JavaScript 对 HTML 事件作出反应。JavaScript 能够在事件发生时执行,比如当用户点击某个 HTML 元素时。
JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。
事件是由三部分组成
事件源 事件类型 事件处理程序 我们也称为事件三要素
1.事件源:事件被触发的对象 -->按钮对象
2.事件类型:如何触发?触发什么事件?例如鼠标点击,键盘按下等…
3.事件处理程序:通过一个函数赋值的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 事件是由三部分组成
// 事件源 事件类型 事件处理程序 我们也称为事件三要素
// 1.事件源:事件被触发的对象 -->按钮对象
// 2.事件类型:如何触发?触发什么事件?例如鼠标点击,键盘按下等…
// 3.事件处理程序:通过一个函数赋值的方式
window.onload = function(){
// 1.获取dom元素
// 2.给dom元素绑定事件
// 3.声明事件处理程序
var div = document.querySelector('div')
var button = document.querySelector('button')
// console.log(div, button);//<div> <button onclick="handler()">
button.onclick = function(){
div.style.width = '100px'
div.style.height = '100px'
div.style.backgroundColor = 'pink'
div.style.fontSize = '30px'
div.innerText = 'hello Evan'
}
// function handler(){
// div.style.width = '100px'
// div.style.height = '100px'
// div.style.backgroundColor = '100px'
// div.style.fontSize = '30px'
// div.innerText = 'hello Evan'
// } 会报错
}
</script>
</head>
<body>
<div>我是div</div>
<!-- handler()事件处理程序 -->
<button onclick="handler()">点击我</button>
</body>
</html>
执行事件的步骤
1.获取事件源
2.注册事件(绑定事件)
3.采用函数赋值形式添加事件处理程序
常用事件:
-
当用户点击鼠标时
-
当网页加载后
-
当图像加载后
-
当鼠标移至元素上时
-
当输入字段被改变时
-
当 HTML 表单被提交时
-
当用户敲击按键时
一.事件流
事件流描述了页面接收事件的顺序。
1.事件冒泡(IE事件流)
事件冒泡:事件从内向外触发
IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。
阻止事件冒泡
使用阻止事件冒泡之前,先要知道DOM事件默认提供的一个对象,HTML DOM Event对象。
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
event.stopPropagation()
直接在对应方法中使用event.stopPropagation()便可阻止事件冒泡。
注意:如果点击方法时需要同时传递其他参数和event,直接传递event这个单词即可
onclick="test(123,event)"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.outer{
width: 300px;
height: 300px;
background-color: skyblue;
margin: 0 auto;
padding: 50px;
box-sizing: border-box;
}
.center{
width: 200px;
height: 200px;
background-color: pink;
padding: 50px;
box-sizing: border-box;
}
.inner{
width: 100px;
height: 100px;
background-image: linear-gradient(to right, hotpink, orange, blue);
}
</style>
<script>
// 事件流描述了页面接收事件的顺序。
window.onload = function(){
// 给dom元素绑定事件
// 1.获取dom元素
// 2.给dom绑定事件
var outer = document.querySelector('.outer')
var center = document.querySelector('.center')
var inner = document.querySelector('.inner')
outer.onclick = function(){
alert('我是outer')
console.log(event.target, '触发事件目标源3');
console.log(event.currentTarget, '当前正在执行事件的dom元素3');
// <div class="inner">触发事件目标源3
// <div class="outer"> 当前正在执行事件的dom元素3
}
center.onclick = function(){
alert('我是center')
// event.stopPropagation(); // 运行到center停
console.log(event.target, '触发事件目标源2');
console.log(event.currentTarget, '当前正在执行事件的dom元素2');
//<div class="inner">触发事件目标源2
// <div class="center"> 当前正在执行事件的dom元素2
}
inner.onclick = function(){
alert('我是inner')
// 阻止事件冒泡 event 表示当前事件对象
// console.log(event, '事件对象');
click { target: div.inner, buttons: 0, clientX: 994, clientY: 144, layerX: 994, layerY: 144 }
// event.stopPropagation() //只运行inner
// target 指向事件触发目标源 谁触发的事件 target就是谁
// currentTarget 当前正在执行事件的dom元素 谁正在执行 currentTarget 就是谁
console.log(event.target, '触发事件目标源1');
console.log(event.currentTarget, '当前正在执行事件的dom元素1');
// <div class="inner">触发事件目标源1
// <div class="inner"> 当前正在执行事件的dom元素1
}
}
</script>
</head>
<body>
<!-- 事件流:描述了页面接收事件的顺序 -->
<!-- 1.事件冒泡 -->
<!-- 2.事件捕获 -->
<!--
事件流:描述的是页面接受事件的顺序
分为事件冒泡和事件捕获
事件冒泡:事件从内向外触发
事件捕获:事件从外向内触发
事件流机制:事件捕获--到达目标--事件冒泡
-->
<div class="outer">
<div class="center">
<div class="inner"></div>
</div>
</div>
</body>
</html>
2.dom0级事件和dom2级事件
dom0级事件绑定 on事件类型 dom0级不可以追加同一类型事件 追加执行最后一次事件处理程序
dom2级事件 addEventListener('事件类型', 事件处理程序, true/false)
true表示执行事件捕获 false表示执行事件冒泡(默认值)
dom2级事件事件可以追加事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var btn = document.querySelector('button')
// dom0级事件绑定 on事件类型 dom0级事件不可以追加同一类型事件 追加执行最后一次事件处理程序
// 绑定第一个事件
btn.onclick = function(){
console.log(this);//<button>
}
// 追加事件
btn.onclick = function(){
alert('第二次事件')
}
// dom0事件解绑 绑定解绑都是重新赋值的操作
btn.onclick = null
// dom2级事件 addEventListener('事件类型', 事件处理程序, true/false)
// true表示执行事件捕获 false表示执行事件冒泡
// dom2级事件事件可以追加事件
function handler1(){
console.log(this);
}
function handler2(){
alert('第二次事件')
}
btn.addEventListener('click', handler1)
btn.addEventListener('click', handler2)
// dom2级事件解绑 removeEventListener('事件类型', 具名函数事件处理程序,)
// // function add(){} 具名函数
btn.removeEventListener('click', handler1)
/**
* dom0级和dom2级事件区别?
* 1.dom0级绑定事件使用on关键字绑定 解绑on事件类型设置为null
* 2.dom2级事件绑定使用addEventListener 解绑使用removeEventListener
* 3.dom0级事件不可以追加同一类型事件 追加就是覆盖
* 4.dom2级事件可以追加同一类型事件 追加就依次执行
*/
}
</script>
</head>
<body>
<button>点击我</button>
</body>
</html>
3.事件捕获(Netscape事件流)
事件捕获:事件从外向内触发
Netscape Communicator 团队提出了另一种名为事件捕获的事件流。事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.outer{
width: 300px;
height: 300px;
background-image: radial-gradient(hotpink, skyblue, orange);
margin: 0 auto;
padding: 50px;
box-sizing: border-box;
}
.center{
width: 200px;
height: 200px;
background-color: pink;
padding: 50px;
box-sizing: border-box;
}
.inner{
width: 100px;
height: 100px;
background-image: linear-gradient(to right, hotpink, orange, blue);
}
</style>
<script>
window.onload = function(){
var outer = document.querySelector('.outer')
var center = document.querySelector('.center')
var inner = document.querySelector('.inner')
function handler1(){
console.log('outer');
}
function handler2(){
console.log('center');
}
function handler3(){
console.log('inner');
}
// dom2级事件 addEventListener('事件类型', 事件处理程序, true/false)
// true表示执行事件捕获(由外向内) false表示执行事件冒泡(默认)(由内向外)
outer.addEventListener('click', handler1, true)
center.addEventListener('click', handler2, true)
inner.addEventListener('click', handler3, true)
}
</script>
</head>
<body>
<div class="outer">
<div class="center">
<div class="inner"></div>
</div>
</div>
</body>
</html>
4.DOM事件流
事件流机制:事件捕获--到达目标--事件冒泡
DOM2 Events 规范规定事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。
注意:所有现代浏览器都支持 DOM 事件流,只有 IE8 及更早版本不支持。
二.阻止事件默认行为
preventDefault()方法
用于阻止特定事件的默认动作。比如,链接的默认行为就是在被单击时导航到 href 属性指定的 URL或是修改表单提交的默认事件。如果想阻止这些行为,可以在 onclick 事件处理程序中取消
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var input = document.querySelector('input');
var a = document.querySelector('a');
input.onclick = function(){
// 阻止input标签默认提交行为
event.preventDefault()
}
a.onclick = function(){
// 阻止a标签默认跳转行为
event.preventDefault()
}
}
</script>
</head>
<body>
<form action="text.php">
<input type="submit" value="提交">
</form>
<a href="https:///www.baidu.com">跳转到百度</a>
</body>
</html>
三.事件委托
在 JavaScript 中,页面中事件处理程序的数量与页面整体性能直接相关。原因有很多。首先,每个函数都是对象,都占用内存空间,对象越多,性能越差。其次,为指定事件处理程序所需访问 DOM 的次数会先期造成整个页面交互的延迟。只要在使用事件处理程序时多注意一些方法,就可以改善页面性能。
事件委托就是当事件触发时,把要做的事委托给父元素(或父元素的父元素)来处理。也就是:利用冒泡的原理,把事件加到父级上,通过判断事件来源的子集,执行相应的操作。使用事件委托技术能让你避免对特定的每个节点添加事件监听器。
事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,click 事件冒泡到 document。这意味着可以为整个页面指定一个 onclick 事件处理程序,而不用为每个可点击元素分别指定事件处理程序。
事件委托(事件代理)
原理:利用事件冒泡 只指定一个事件处理程序 就可以管理某一类型的事件
将本应该绑定给子元素事件绑定给父元素
目的:优化页面性能 减少事件的执行 减少浏览器的重排(回流)和重绘 给新增的元素绑定事件
<一>给所有li绑定事件 点击的时候背景色变成红色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var ul = document.querySelector('ul');
// 给所有li绑定事件 点击的时候背景色变成红色
var lis = document.querySelectorAll('li');
for(var i=0;i<lis.length;i++){
lis[i].onclick = function(){
this.style.backgroundColor = 'red'
}
}
var newLi = document.createElement('li');
newLi.innerText ='第11个li'
ul.appendChild(newLi);
}
</script>
</head>
<body>
<ul>
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第4个li</li>
<li>第5个li</li>
<li>第6个li</li>
<li>第7个li</li>
<li>第8个li</li>
<li>第9个li</li>
<li>第10个li</li>
</ul>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var ul = document.querySelector('ul');
// 给所有li绑定事件 点击的时候背景色变成红色
var lis = document.querySelectorAll('li');
// for(var i=0;i<lis.length;i++){
// lis[i].onclick = function(){
// this.style.backgroundColor = 'red'
// }
// }
var newLi = document.createElement('li');
newLi.innerText ='第11个li'
ul.appendChild(newLi);
/**
* 事件委托 将子元素事件代理给父元素 只绑定一次事件 管理一类事件
*/
ul.onclick = function(){
// event 事件对象 event.target
// event.target.style.backgroundColor = 'red'
var target = event.target;
if(target.tagName === 'LI'){
target.style.backgroundColor = 'red'
}
}
}
</script>
</head>
<body>
<!--
事件委托(事件代理) *****
原理:利用事件冒泡 只指定一个事件处理程序 就可以管理某一类型的事件
将本应该绑定给子元素事件绑定给父元素
目的:优化页面性能 减少事件的执行 减少浏览器的重排(回流)和重绘 给新增的元素绑定事件
-->
<ul>
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第4个li</li>
<li>第5个li</li>
<li>第6个li</li>
<li>第7个li</li>
<li>第8个li</li>
<li>第9个li</li>
<li>第10个li</li>
</ul>
</body>
</html>
<二>点击不同li内部内容 发生不同改变
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var ul = document.querySelector('ul');
// 点击不同li内部内容 发生不同改变
var item1 = document.querySelector('#frist');
var item2 = document.querySelector('#second');
var item3 = document.querySelector('#three');
item1.onclick = function(){
this.innerText = 'hello html'
}
item2.onclick = function(){
this.innerText = 'hello css'
}
item3.onclick = function(){
this.innerText = 'hello js'
}
}
</script>
</head>
<body>
<ul>
<li id="frist">li标签</li>
<li id="second">li标签</li>
<li id="three">li标签</li>
</ul>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var ul = document.querySelector('ul');
// 点击不同li内部内容 发生不同改变
ul.onclick = function(){
var target = event.target;
console.log(target);
// <li id="frist">
// <li id="second">
// <li id="three">
switch(target.id){
case 'frist':
target.innerText = 'hello html';
break;
case 'second':
target.innerText = 'hello css';
break;
case 'three':
target.innerText = 'hello js';
break;
default:
target.innerText = '我是li标签'
}
}
}
</script>
</head>
<body>
<ul>
<li id="frist">li标签</li>
<li id="second">li标签</li>
<li id="three">li标签</li>
</ul>
</body>
</html>
四.事件类型
<一>用户界面事件(UIEvent):涉及与 BOM 交互的通用浏览器事件。
1.select 绑定选择事件 在文本框(<input>或 textarea)上当用户选择了一个或多个字符时触发。
var input = document.querySelector('input');
input.onselect = function(){
console.log('我被选择了');
// 通过window.getSelection()获取到选中的部分
console.log(window.getSelection().toString());
}
2.resize 方法 窗口进行缩放时候触发
document.body.onresize = function(){
console.log(window.outerHeight,window.outerWidth)//942 1187
}
3.scroll 事件 绑定滚动事件
var div = document.querySelector('div');
div.onscroll = function(){
console.log('我在滚动')
}
4.load
在 window 上当页面加载完成后触发,在窗套(<frameset>)上当所有窗格(<frame>)都加载完成后触发,在<img>元素上当图片加载完成后触发,在<object>元素上当相应对象加载完成后触发。
<script>
window.onload = function () {
console.log('onload');
}
</script>
5.unload
当页面完全卸载后在window上触发,当所有框架都卸载后在框架集上触发,当嵌入的内容卸载完毕后在<object>上触发。
<二>焦点事件(FocusEvent):在元素获得和失去焦点时触发。
聚焦focus 失焦 blur
input.onfocus = function(){
this.style.backgroundColor = 'pink'
}
input.onblur = function(){
console.log('请单击输入框')
}
focusin
当元素获得焦点时触发。这个事件是 focus 的冒泡版。
focusout
当元素失去焦点时触发。这个事件是 blur 的冒泡版。
<三>鼠标事件(MouseEvent):使用鼠标在页面上执行某些操作时触发。
1.双击 dbclick
div.ondblclick = function(){
console.log('我被双击了')
}
2.鼠标移入mouseenter 鼠标移除mouseleave 鼠标一直移动mousemove
div.onmouseenter = function(){
console.log('鼠标移入')
}
div.onmouseleave = function(){
console.log('鼠标移出')
}
div.onmousemove = function(){
console.log('鼠标一直在移动')
}
-
click
在用户单击鼠标主键(通常是左键)或按键盘回车键时触发。这主要是基于无障碍的考虑,让键盘和鼠标都可以触发 onclick 事件处理程序。
-
dblclick
在用户双击鼠标主键(通常是左键)时触发。这个事件不是在 DOM2 Events 中定义的,但得到了很好的支持,DOM3 Events 将其进行了标准化。
-
mousedown
在用户按下任意鼠标键时触发。这个事件不能通过键盘触发。
-
mouseenter
在用户把鼠标光标从元素外部移到元素内部时触发。这个事件不冒泡,也不会在光标经过后代元素时触发。mouseenter 事件不是在 DOM2 Events 中定义的,而是 DOM3 Events中新增的事件。
-
mouseleave
在用户把鼠标光标从元素内部移到元素外部时触发。这个事件不冒泡,也不会在光标经过后代元素时触发。mouseleave 事件不是在 DOM2 Events 中定义的,而是 DOM3 Events中新增的事件。
-
mousemove
在鼠标光标在元素上移动时反复触发。这个事件不能通过键盘触发。
-
mouseout
在用户把鼠标光标从一个元素移到另一个元素上时触发。移到的元素可以是原始元素的外部元素,也可以是原始元素的子元素。这个事件不能通过键盘触发。
-
mouseover
在用户把鼠标光标从元素外部移到元素内部时触发。这个事件不能通过键盘触发。
-
mouseup
在用户释放鼠标键时触发。这个事件不能通过键盘触发。
3.滚轮事件(WheelEvent):使用鼠标滚轮(或类似设备)时触发。
mousewheel 鼠标滚轮事件
4.键盘事件(KeyboardEvent):使用键盘在页面上执行某些操作时触发。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var input = document.querySelector('input');
//键盘按下事件 keydown 按键 keyCode
input.onkeydown = function(){
console.log(event.keyCode)
}
// 键盘抬起事件 keyup
input.onkeyup = function(){
console.log('我被抬起了')
}
// 键盘持续按下事件
input.onkeypress=function(){
console.log('持续按下')
}
//输入框输入事件 获取文本输入值
input.addEventListener('textInput',function(event){
console.log(event.data)
});
}
</script>
</head>
<body>
<input type="text">
</body>
</html>
5.输入事件(InputEvent):向文档中输入文本时触发。