1、什么是事件
指在特定条件下触发的操作或响应。事件可以是用户与网页交互时引起的动作,例如点击按钮、提交表单、鼠标移动等,也可以是由浏览器或其他代码触发的动作,如页面加载完成、时间到达等。
我们可以通过添加事件处理程序来响应各种事件。事件处理程序是一段JavaScript代码,用于定义事件发生时要执行的操作。通过将事件处理程序绑定到特定的HTML元素上,当事件被触发时,相应的代码将被执行。
事件驱动编程是一种常见的编程范式,在Web开发中尤为重要。它允许我们对用户的操作做出即时反应,提供交互性和动态性的体验。
以下是一个简单的例子,演示了如何使用JavaScript为按钮添加点击事件处理程序:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button id="myButton">点击我</button>
<script>
// 获取按钮元素
var button = document.getElementById("myButton");
// 添加点击事件处理程序
button.addEventListener("click", function(){
alert("按钮被点击了!");
});
</script>
</body>
</html>
以上代码将在按钮被点击时弹出一个提示框,显示"按钮被点击了!"。
2、事件三要素
-
触发器(Event Trigger):触发器是引起事件发生的原因或条件。它可以是用户的交互操作,如点击按钮、鼠标移动等,也可以是其他代码的执行结果,比如页面加载完成、定时器到达等。触发器定义了何时发生事件。
-
监听器(Event Listener):监听器是负责监听特定事件是否发生的对象或函数。它会注册在某个元素或全局范围内,等待触发器的信号。当事件被触发时,监听器会接收到通知,并执行相应的操作。一个事件可以有多个监听器。
-
处理程序(Event Handler):处理程序是监听器接收到事件后所执行的代码块或函数。它定义了事件发生时要执行的操作,例如更新页面内容、发送网络请求、验证表单等。处理程序是实际对事件作出响应的部分。
这三要素共同构成了一个完整的事件模型。触发器触发事件,监听器接收并传递事件,处理程序执行对事件的响应。通过事件模型,我们可以实现网页的交互功能,获得更好的用户体验。
3、事件的类型
-
鼠标事件:
- click:单击鼠标时触发该事件。
- dblclick:双击鼠标时触发该事件。
- mousedown:按下鼠标按钮时触发该事件。
- mouseup:松开鼠标按钮时触发该事件。
- mousemove:鼠标指针移动时触发该事件。
- mouseover:鼠标指针移至元素之上时触发该事件(无法阻止冒泡)。
- mouseout:鼠标指针移出元素时触发该事件(无法阻止冒泡)。
- mouseenter:鼠标指针移至元素之上时触发该事件(可以阻止冒泡)。
- mouseleave:鼠标指针移出元素时触发该事件(可以阻止冒泡)。
- mousewheel:转动鼠标滚轮时触发该事件。
- scroll:滚动元素的滚动条时触发该事件。
-
键盘事件:
- keydown:键盘按下事件。
- keyup:键盘松开事件。
- keypress:按键被按住并松开事件。
-
表单事件:
- blur:当元素失去焦点时触发该事件。
- focus:当元素获得焦点时触发该事件。
- change:当元素的值改变时触发该事件。
- input:当元素获得用户输入时触发该事件。
- invalid:当元素的值无效时触发该事件。
- select:当用户选取元素的内容时触发该事件。
- submit:当提交表单时触发该事件。
-
窗口事件:
- load:当页面加载完毕后触发,可以用于执行初始化操作或加载资源。
- unload:页面离开(关闭或刷新)事件。
- blur:当窗口失去焦点时触发。
- focus:当窗口获得焦点时触发。
- resize:当窗口大小调整时触发,可以用于响应页面布局的变化。
- scroll:当窗口滚动时触发,可以用于实现滚动监听或动态加载内容等功能。
- storage:当 Web Storage 区域更新时(存储空间中的数据发生变化时)运行脚本。
-
触摸事件:
- touchstart:当手指触摸屏幕上的元素时触发。
- touchmove:当手指在屏幕上滑动时触发,会连续触发多次。
- touchend:当手指离开屏幕时触发。
- touchcancel:当触摸事件被取消时触发,例如由于系统事件(如电话呼叫)导致触摸结束。
-
网络事件:
- load:当页面或资源加载完成时触发,例如 <img> 元素加载完成、整个页面加载完成等。
- error:当页面或资源加载错误时触发,表示加载失败。
- unload:当页面被卸载或关闭时触发,可以用于执行一些清理操作。
- readystatechange:当 XMLHttpRequest 对象的请求状态发生变化时触发,用于检测请求的进度和状态。
- online:当设备处于在线状态时触发,表示网络连接恢复。
- offline:当设备处于离线状态时触发,表示网络连接丢失。
- beforeunload:在页面即将关闭或离开之前触发,可以用于向用户显示确认对话框,提示是否要离开页面。
-
媒体事件:
- onabort:当发生中止事件时运行脚本。
- oncanplay:当媒介能够开始播放但可能因缓冲而需要停止时运行脚本。
- oncanplaythrough:当媒介能够无需因缓冲而停止即可播放至结尾时运行脚本。
- ondurationchange:当媒介长度改变时运行脚本。
- onemptied:当媒介资源元素突然为空时(网络错误、加载错误等)运行脚本。
- onended:当媒介已抵达结尾时运行脚本。
- onerror:当在元素加载期间发生错误时运行脚本。
- onloadeddata:当加载媒介数据时运行脚本。
- onloadedmetadata:当媒介元素的持续时间以及其它媒介数据已加载时运行脚本。
- onloadstart:当浏览器开始加载媒介数据时运行脚本。
- onpause:当媒介数据暂停时运行脚本。
- onplay:当媒介数据将要开始播放时运行脚本。
- onplaying:当媒介数据已开始播放时运行脚本。
- onprogress:当浏览器正在取媒介数据时运行脚本。
- onratechange:当媒介数据的播放速率改变时运行脚本。
- onreadystatechange:当就绪状态(ready-state)改变时运行脚本。
- onseeked:当媒介元素的定位属性不再为真且定位已结束时运行脚本。
- onseeking:当媒介元素的定位属性为真且定位已开始时运行脚本。
- onstalled:当取回媒介数据过程中(延迟)存在错误时运行脚本。
- onsuspend:当浏览器已在取媒介数据但在取回整个媒介文件之前停止时运行脚本。
- ontimeupdate:当媒介改变其播放位置时运行脚本。
- onvolumechange:当媒介改变音量或当音量被设置为静音时运行脚本。
- onwaiting:当媒介已停止播放但打算继续播放时运行脚本。
-
拖拽事件:
- ondragstart:当开始拖拽元素时触发。
- ondrag:在拖拽过程中持续触发,表示拖拽元素的位置正在改变。
- ondragenter:当一个可拖拽元素进入目标元素的范围内时触发。
- ondragover:在拖拽元素悬停在目标元素上方时持续触发。
- ondragleave:当一个可拖拽元素离开目标元素的范围时触发。
- ondrop:在释放拖拽元素时触发,表示拖拽元素已经被放置到目标元素内部。
- ondragend:当拖拽操作结束(无论是否成功放置)时触发。
9.其它事件 :
1.ontoggle:当用户打开或关闭 <details> 元素时触发。
ontoggle事件的示例代码:
<details ontoggle="handleToggle(event)">
<summary>点击此处展开/收起内容</summary>
<p>这是可折叠的内容。</p>
</details>
<script>
function handleToggle(event) {
if (event.target.open) {
console.log("内容已展开");
} else {
console.log("内容已收起");
}
}
</script>
示例代码:
<!DOCTYPE html>
<html>
<head>
<title>事件示例</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: #ccc;
margin-bottom: 10px;
}
.box:hover {
background-color: yellow;
}
</style>
<script>
function handleClick() {
alert("点击事件触发");
}
function handleMouseOver() {
alert("鼠标移入事件触发");
}
function handleMouseOut() {
alert("鼠标移出事件触发");
}
function handleKeyDown(event) {
if (event.key === "Enter") {
alert("按下回车键");
}
}
function handleFormSubmit(event) {
event.preventDefault(); // 阻止表单提交的默认行为
var input = document.getElementById("nameInput");
alert("输入的姓名是:" + input.value);
}
</script>
</head>
<body>
<div class="box" onclick="handleClick()" onmouseover="handleMouseOver()" onmouseout="handleMouseOut()"></div>
<input type="text" onkeydown="handleKeyDown(event)">
<form onsubmit="handleFormSubmit(event)">
<label for="nameInput">姓名:</label>
<input type="text" id="nameInput">
<button type="submit">提交</button>
</form>
</body>
</html>
在上面的例子中:
<div>
元素具有一个点击事件(onclick
),一个鼠标移入事件(onmouseover
)和一个鼠标移出事件(onmouseout
)。当点击、移入和移出该元素时,会触发相应的事件处理函数,并弹出对应的提示框。- 在文本输入框中按下回车键会触发
handleKeyDown
函数,如果按下的是回车键,则弹出一个提示框。 - 在表单中点击提交按钮或按下回车键会触发
handleFormSubmit
函数,阻止表单的默认提交行为,弹出一个提示框显示输入的姓名。
拓展知识:
当事件的响应函数被触发时,浏览器会将一个事件对象作为参数传递给响应函数。这个事件对象包含了与事件相关的信息和属性。
在现代浏览器中(除了 IE8 及更早版本),可以直接通过函数参数获取事件对象,例如:
element.addEventListener('click', function(event) {
// 使用 event 对象进行操作
});
然而,在 IE8 及更早版本的浏览器中,事件对象作为全局变量 window.event 存在。为了兼容老版本的 IE 浏览器,可以使用以下代码:
element.attachEvent('onclick', function() {
var event = window.event;
// 使用 event 对象进行操作
});
上述代码中,通过将 window.event 赋值给局部变量 event,使代码在不同浏览器下都能正常使用事件对象。
综合起来,通常可以使用以下方式来处理事件对象的兼容性:
element.addEventListener('click', function(event) {
event = event || window.event; // 兼容IE8及更早版本的浏览器
// 使用 event 对象进行操作
});
这样,无论是现代浏览器还是 IE8 及更早版本的浏览器,都可以正确地获取到事件对象并进行相应的操作。
4 、事件流模型
下图显示的就是事件捕捉和事件冒泡的流程。
下图显示的是DOM事件流的流程。
- 冒泡事件流:由最具体的元素开始接收事件,并往上传播,直至最外层元素。
- 捕获事件流:由最不具体的元素接收事件,并往下传播,直至最具体的元素。
- DOM事件流:包括了事件捕获、目标阶段和事件冒泡三个阶段,从最外层元素开始接收事件,依次经过目标元素,最后回到最外层元素。(事件捕获 → 目标阶段 → 事件冒泡)
代码示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
div,
ul,
li {
width: 100px;
height: 50px;
}
div {
background-color: green;
}
ul {
background-color: red;
}
li {
background-color: yellow;
}
</style>
</head>
<body>
<div>
帅哥
<ul>
帅哥
<li>
帅哥
<button>
帅哥
</button>
</li>
</ul>
</div>
</body>
<script>
//button
var button_ = document.getElementsByTagName('button')[0];
button_.addEventListener('click', function() {
console.log('4');
}, false)
//li
var li_ = document.getElementsByTagName('li')[0];
li_.addEventListener('click', function() {
console.log('3');
}, true)
//ul
var ul_ = document.getElementsByTagName('ul')[0];
ul_.addEventListener('click', function() {
console.log('2');
}, false)
//div
var div_ = document.getElementsByTagName('div')[0];
div_.addEventListener('click', function() {
console.log('1');
}, true)
</script>
</html>
点击按钮、li元素、ul元素和div元素时,相应的事件监听器会触发,并在控制台中打印不同的数字:
- 当点击按钮时,控制台会打印出数字4。
- 当点击li元素时,控制台会打印出数字3。
- 当点击ul元素时,控制台会打印出数字2。
- 当点击div元素时,控制台会打印出数字1。
注意:在addEventListener方法中,最后一个参数为布尔值,用于指定事件是否在捕获阶段进行处理。设置为true时,表示在捕获阶段处理事件;设置为false时,表示在冒泡阶段处理事件。
所以点击按钮后会输出:
5、事件对象参数
1.概述: 事件触发后会产生一个事件对象,其中包含与事件相关的信息。这个事件对象会以参数的形式传递给事件处理函数,因此事件处理函数默认会有一个事件对象参数。要使用这个事件对象,只需在事件处理函数中定义一个形参即可。
2.
当鼠标触发事件(如onclick、onmouseover)时,可以使用以下属性来获取相关信息:
- target:获取触发事件的元素。
- srcElement:获取事件源对象
- type:获取事件类型
- currentTarget:获取当前正在处理事件的元素(在事件冒泡时可能与target不同)。
- clientX、clientY:获取当前鼠标在网页上的横、纵坐标,只跟网页的可视区域有关
- pageX、pageY:获取相对于整个页面的鼠标位置。
- offsetX、offsetY:获取相对于事件源元素的鼠标位置。
- screenX、screenY:获取当前鼠标在当前显示器的横坐标、纵坐标
- dragX:代表拖拽操作的水平位置,通常表示元素相对于某个参考点(如文档左上角)的横向位置。
- dragY:代表拖拽操作的垂直位置,通常表示元素相对于某个参考点的纵向位置。
- button:获取鼠标点击的哪个键
而键盘触发的事件时,可以使用以下属性来获取相关信息:
- keyCode:获取按下的键盘按键对应的字符代码。
- shiftKey、ctrlKey、altKey、metaKey:判断是否同时按下了Shift、Ctrl、Alt和
Meta(Windows键或Command键)键。
此外,还有一些常用方法用于事件处理:
- preventDefault():阻止事件的默认行为。
- stopPropagation():停止事件的进一步传播,防止事件冒泡。
代码示例:
<!DOCTYPE html>
<html>
<head>
<title>获取鼠标和键盘事件信息示例</title>
<script>
function handleClick(event) {
var target = event.target;
var currentTarget = event.currentTarget;
var clientX = event.clientX;
var clientY = event.clientY;
var pageX = event.pageX;
var pageY = event.pageY;
var offsetX = event.offsetX;
var offsetY = event.offsetY;
var keyCode = event.keyCode;
var shiftKey = event.shiftKey;
var ctrlKey = event.ctrlKey;
var altKey = event.altKey;
console.log('target:', target);
console.log('currentTarget:', currentTarget);
console.log('clientX:', clientX);
console.log('clientY:', clientY);
console.log('pageX:', pageX);
console.log('pageY:', pageY);
console.log('offsetX:', offsetX);
console.log('offsetY:', offsetY);
console.log('keyCode:', keyCode);
console.log('shiftKey:', shiftKey);
console.log('ctrlKey:', ctrlKey);
console.log('altKey:', altKey);
}
</script>
</head>
<body>
<button onclick="handleClick(event)">点击我</button>
</body>
</html>
在上面的例子中,当用户点击"点击我"按钮时,会被handleClick函数处理,该函数接收一个event参数,通过访问event对象的属性来获取有关鼠标和键盘事件的信息。调试输出将显示相关信息。
下面运用事件对象参数写个有意思的html页面
<!DOCTYPE html>
<html>
<head>
<style>
/* 设置可拖拽元素的样式 */
.draggable {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
cursor: move;
}
</style>
</head>
<body>
<!-- 可拖拽的元素 -->
<div class="draggable">Drag me!</div>
<script>
function enableDragging(element) {
var dragging = false;
var dragX, dragY;
// 当鼠标按下时开始拖拽
document.addEventListener('mousedown', function(e) {
dragging = true;
dragX = e.clientX - element.offsetLeft;
dragY = e.clientY - element.offsetTop;
});
// 当鼠标移动时,如果正在拖拽,则更新元素的位置
document.addEventListener('mousemove', function(e) {
if (dragging) {
element.style.left = (e.clientX - dragX) + 'px';
element.style.top = (e.clientY - dragY) + 'px';
}
});
// 当鼠标释放时结束拖拽
document.addEventListener('mouseup', function() {
dragging = false;
});
}
// 获取可拖拽元素并启用拖拽功能
var draggableElement = document.querySelector('.draggable');
enableDragging(draggableElement);
</script>
</body>
</html>
在上述代码中,创建了一个可拖拽的div元素,并为其添加了.draggable类。CSS样式设置了它的宽度、高度、背景颜色以及定位属性。
JavaScript部分定义了enableDragging函数,它注册了mousedown、mousemove和mouseup事件监听器来实现拖拽效果。
当鼠标按下(mousedown事件)时,开始拖拽:
1.将dragging标志设置为true。
2.计算鼠标位置与元素左上角的偏移量(dragX和dragY),以便在拖拽过程中正确地更新元素位置。
当鼠标移动(mousemove事件)时,如果处于拖拽状态,则根据鼠标的位置更新元素的左边距和上边距,从而实现拖拽效果。
当鼠标松开(mouseup事件)时,将dragging标志设置为false,拖拽结束。
最后,通过querySelector方法选择.draggable类,获取到可拖拽的元素,并调用enableDragging函数来启用拖拽功能。