JavaScript入门⑧-事件总结大全
JavaScript入门系列目录
- JavaScript入门①-基础知识筑基
- JavaScript入门②-函数(1)基础{浅出}
- JavaScript入门③-函数(2)原理{深入}执行上下文
- JavaScript入门④-万物皆对象:Object
- JavaScript入门⑤-欲罢不能的对象、原型与继承
- JavaScript入门⑥-WEB浏览器API
- JavaScript入门⑦-DOM操作大全
- JavaScript入门⑧-事件总结大全
- JavaScript入门⑨-异步编程●异世界之旅
- JavaScript入门⑩-ES6归纳总结
01、事件基础
1.1、事件简介
事件(Event)是JavaScript的心脏,触发各种交互,让网页动起来。事件是浏览器网页可以监测到的行为,如页面加载、鼠标点击、键盘按键等。在这些事件中可以自定义事件处理程序,用于实现各种业务需求。
事件对象的继承关系:
常见的事件类型、事件如下:
鼠标事件(event) | |
---|---|
click(event) | 点击触发,通常是鼠标左键在一个元素上被按下并放开时 |
dblclick | 双击触发事件 |
contextmenu | 鼠标右键点击触发 |
mousedown、mouseup | 鼠标按下、弹起时触发 |
mousemove | 鼠标在元素上移动时触发 |
onmouseover、mouseout | 鼠标移入、移出元素区域时触发 |
mouseenter、mouseleave | 鼠标移入、移出元素区域时触发,与上面不同的是不会冒泡 |
dragstart、dragend | 拖放事件(drag/dræɡ/拖) |
键盘事件(event) | |
keydown、keyup | 键盘按键按下、松开时触发 |
表单事件(event) | |
blur(event)、focusout() | 元素失去焦点,blur不会冒泡 (blue /blɜːr/ 模糊 /不乐/) |
focus、focusin | 元素获取焦点时触发,focus不会冒泡 |
from.submit | 提交表单form时触发,可用于表单校验 |
change | 值发生变化时触发,文本框是在值变化且失去焦点是才触发 |
input | 输入值改变时触发,event.preventDefault() 无法阻止,因为已经改变了 |
Document 事件(event) | 文档生命周期:DOMContentLoaded ️ load ️ beforeunload ️ unload |
doc.DOMContentLoaded | 已加载 HTML并构建好DOM树,外部资源(image、css)可能尚未加载完成 - 如果遇到 <script> 标签,会执行(包括外部的资源)然后才继续后面的DOM加载,要注意!async、defer标记的除外(只支持外部js资源) |
window.load | 文档完全加载完成,包括图片、样式都准备好了。可用于window、element |
window.beforeunload | 当用户正在离开页面时,不可取消,好像也不能干什么。 |
window.unload | 用户几乎已经离开了,同上 |
doc.readystatechange | 文档状态变化时触发,可跟踪文档加载状态readyState |
onerror | 加载出现错误,用于元素 |
scroll | 滑动条滚动事件,具有滚动的视图元素。用于window、element |
ClipboardEvent事件 | 事件参数对象clipboardData 由于安全限制,方法无法使用 |
cut,copy,paste | 剪切、拷贝、粘贴时触发 |
e.clipboardData | 保存了一个DataTransfer对象,用于存放数据,该对象也用于拖放 |
CSS事件(event) | |
transitionend | 一个元素 CSS 动画完成时ele.addEventListener("transitionend", func) |
1.2、事件的绑定
① HTML事件:HTML中绑定(调用)事件处理程序,<button onclick="func(event);func2()">button</button>
,注意加括号()。
② JS绑定事件(DOM-0级事件):button.onclick = function() {}
,和HTML绑定一样,只能绑定一个事件处理程序。不能用setAttribute设置事件,因为设置的是字符串值。
③ 注册事件(DOM-2级事件):
- ele.addEventListener(event,func[, options]) :注册事件,推荐的常用方式,可添加多个事件处理程序,但同一个事件类型不可添加同一个handler对象。参数options为配置信息,如是否冒泡。
- ele.removeEventListener(event,func[, options]) :必须是与添加时相同(恒等)的参数,不可移除匿名函数事件。
④ 事件处理对象handleEvent
除了注册事件方法,还可用将一个包含handleEvent
方法的对象注册到事件处理程序,触发事件时调用对象的handleEvent
方法。so,只要对象中包含handleEvent
方法即可,任何对象、类的实例都可以。
<div id="ediv">
<span id="espan" onclick="console.log('html bind')">span</span>
<button id="btn" onclick="console.log('html bind')">button</button>
</div>
<script>
function func1(event) {
console.log(event.currentTarget, event.target); //div span
console.log("event.cancleable:" + event.cancelable) //event.cancleable:true
console.log(event.clientX, event.clientY); //31 363
//取消冒泡
event.cancelBubble = true;
event.stopPropagation();
event.stopImmediatePropagation(); //取消冒泡,以及元素同类型的其他事件
//取消默认事件,如checkbox,a元素的默认行为
event.preventDefault();//对自定义事件没用,
}
ediv.addEventListener('click', func1);
ediv.addEventListener('click', e=>console.log(e.currentTarget.localName)); //div,前面取消了则不会执行
ediv.addEventListener('click', ()=>console.log('click me'));
//事件处理对象,调用对象的handelEvent方法执行事件
let eventObj = {
handleEvent(event) {
console.log("handleEvent", this.objName, event);
},
objName: "eventObj",
}
btn.addEventListener("click", eventObj);
</script>
1.3、事件对象event
每一个事件处理程序都有一个event
对象,内置了事件的详细信息。最基础的Event如下,还有很多继承事件对象。
Event属性 | |
---|---|
type | 事件的类型 |
target | 指向事件触发的目标元素,可能为子元素,冒泡中不会改变。originalTarget为非标准(Mozilla) |
currentTarget = this | 指向事件绑定的元素,当前正在处理事假的元素,同 this 。 |
isTrusted | 触发方式,true=用户,false=脚本触发,(Trusted/ˈtrʌstɪd/ 可信的) |
bubbles | 判断事件是否冒泡,bool。( Bubble/ˈbʌb(ə)l/ 冒泡) |
cancelBubble️ | 是否取消冒泡,可设置true阻止冒泡,stopPropagation()的别名 |
composed | 表示事件是否可以穿过 Shadow DOM 和常规 DOM 之间的隔阂进行冒泡,bool |
event.clientX / clientY | 鼠标事件触发的x、y坐标 |
Event 方法 | |
stopPropagation() | 停止向上冒泡(propagation /ˌprɒpəˈɡeɪʃn/ 传播),不影响当前元素的其他注册事件 |
stopImmediatePropagation() | 取消后面的同类型事件的执行,包括冒泡,(Immediate /ɪˈmiːdiət/ 立刻) |
preventDefault() | 取消默认事件行为,如checkbox、<a> ,不影响冒泡。defaultPrevented 判断是否取消了 |
使用event.preventDefault()
可以移除浏览器的默认事件行为,也可以用return false
。
<p>
<input type="checkbox" onclick="return false">
<!--取消默认事件行为:点击无效了-->
<a href="http://www.qq.com" id="qq1" onclick="return false">QQ-1</a>
<a href="http://www.qq.com" id="qq2">QQ-2</a>
<a href="http://www.qq.com" id="qq3">QQ-3</a>
</p>
<script>
//return false 对a标签好像没有作用
qq1.addEventListener("click", () => false);
qq2.addEventListener("click", (event) => event.preventDefault()); //取消默认事件行为
qq3.addEventListener("click", (event) => {
if (!confirm("你确定已满18周岁,要前往[ " + event.target.getAttribute("href") + " ] 吗?")) {
event.preventDefault(); //取消默认事件行为 prevent /prɪˈvent/ 阻止
}
});
</script>
1.4、事件流:冒泡和捕获
事件的触发大都是某一个HTML元素,但这一个元素触发事件时,该事件会在该元素与根节点之间进行顺序传播,路过的元素都会接收到该事件,这个过程称为“事件流”,简单来说就是接收事件的顺序,如下三个阶段。
① 捕获阶段(Capturing phase):(phase /feɪz/ 阶段)
事件(从 Window)逐级向下传播,直到具体的目标元素。捕获阶段实际上很少使用,默认情况下也不会触发,addEventListener 注册事件时通过参数对象options.capture = true
设置在捕获阶段触发事件。ediv.addEventListener("click", fevent2, true /* { capture: true } */);
② 目标阶段(Target phase):事件到达目标元素。
目标元素
event.target
:直接触发事件的、最近的那个元素,也是嵌套最深的那个元素。
③ 冒泡阶段(Bubbling phase):一般常用的是冒泡阶段,这更符合逻辑。
事件从目标元素上开始冒泡,逐级向上春波,直到根节点。几乎所有事件都会冒泡,除了个别的,如blur
、focus
没有冒泡。
<div id="ediv">
<button id="ebutton">button</button>
</div>
<script>
const eles = document.querySelectorAll("#ediv,#ebutton");
for (let ele of eles) {
ele.addEventListener("click", e => console.log("capturing:" + e.currentTarget.localName), true); //捕获
ele.addEventListener("click", e => console.log("bubbling:" + e.currentTarget.tagName)); //冒泡
}
/*
capturing:div
capturing:button
bubbling:BUTTON
bubbling:DIV */
</script>
事件流的两种传播方式其实是IE和Netscape两个公司的不同处理机制导致的。
停止冒泡:
stopPropagation()
、stopImmediatePropagation()
- 注意的区别,
stopPropagation()
只是停止向上冒泡;stopImmediatePropagation()
会额外取消当前元素同类型的后续事件。- 非必要不主动关闭冒泡,谨慎使用,可能会影响其他功能。
1.5、事件委托
事件委托只是事件的一种使用方式而已,基于事件冒泡在,上级节点统一处理从而简化事件的绑定。比如有一堆导航按钮,不需要每个都添加事件,把点击事件委托给其父级元素统一处理。
- 优点:简化代码逻辑,便于修改维护。
- 缺点:事件必须冒泡,如果被阻止了,就嗝屁了;可以忽略的冒泡性能损失。
表格排序示例(委托给表格统一处理):codePen地址
//需求:点击表格标题,对数据进行排序
const table = document.querySelector("#grid");
table.onclick = function (e) {
//点击标题单元格,并且有自定义排序属性
if (e.target.tagName != "TH" || !e.target.hasAttribute("data-sort")) return;
let th = e.target;
sortTable(th.cellIndex, th.dataset.sort);
};
function sortTable(colIndex, type) {
let trs = Array.from(document.querySelectorAll("#grid tbody tr"));
let tbody = table.tBodies[0];
let sortFunc = function (r1, r2) {
switch (type) {
case "number":
return r1.cells[colIndex].innerText - r2.cells[colIndex].innerText;
break;
case "number":
default:
return r1.cells[colIndex].innerText > r2.cells[colIndex].innerText? 1: -1;
break;
}
};
trs = trs.sort(sortFunc);
tbody.append(...trs); //追加已存在的元素,自动进行移动
}
全局提示示例:点击查看【codepen】
1.6、自定义事件
① 创建事件对象:let event = new Event(type[, options])
,使用Event构造函数,或者CustomEvent
自定义事件(参数中有一个detail
字段可存放自定义数据,在事件处理程序中通过event.detail
使用),或其他事件对象MouseEvent、KeyboardEvent。
- type:事件类型,可以是像 "click" 这样的字符串或任意。
- options:具有两个可选属性的对象,是否冒泡
bubbles
(true=冒泡、false),是否取消默认行为ancelable
: (true=阻止、false),默认值都是false。
②触发事件:elem.dispatchEvent(event)
在你需要的地方调用elem.dispatchEvent(event)
触发自定义事件,事件的处理程序和普通事件一样通过addEventListener
添加,不支持on***
。
<p>
<input type="text" id="input">
</p>
<script>
//1、定义事件:当按下F4按钮时触发
let keyF4Click = new CustomEvent("keyF4Click", { detail: { key: "F4" } })
input.addEventListener("keyup", (event => {
if (event.key == "F4")
//2、触发事件
input.dispatchEvent(keyF4Click);
}))
//只能通过addEventListener添加自定义的事件处理程序
input.addEventListener("keyF4Click", (e) => {
input.value += e.detail.key;
})
</script>
02、UI事件
2.2、鼠标事件MouseEvent
鼠标事件(event) | |
---|---|
click(event) | 点击触发,通常是鼠标左键在一个元素上被按下并放开时 |
dblclick | 双击触发事件 |
contextmenu | 鼠标右键点击触发 |
mousedown、mouseup | 鼠标按下、弹起时触发 |
mousemove | 鼠标在元素上移动时触发 |
onmouseover、mouseout | 鼠标移入、移出元素区域时触发 |
mouseenter、mouseleave | 鼠标移入、移出元素区域时触发,与上面不同的是不会冒泡 |
dragstart、dragend | 拖放事件(drag/dræɡ/拖) |
鼠标事件响应顺序:mouseenter
→ mousemove
→ mousedown
→ mouseup
→ click
→ mouseleave
<button id="btn" >button</button>
<script>
btn.addEventListener("mouseenter", (e)=>console.log(1,e.type)); //1 'mouseenter'
btn.addEventListener("mousemove", (e)=>console.log(2,e.type)); //2 'mousemove'
btn.addEventListener("mousedown", (e)=>console.log(3,e.type)); //3 'mousedown'
btn.addEventListener("mouseup", (e)=>console.log(4,e.type)); //4 'mouseup'
btn.addEventListener("click", (e)=>console.log(5,e.type)); //5 'click'
btn.addEventListener("mouseleave", (e)=>console.log(6,e.type)); //6 'mouseleave'
</script>
MouseEvent属性 | |
---|---|
button | 鼠标按下的按钮:0=主按键/左键,1=滚轮中按键,2=次按键/右键 |
clientX / clientY | 鼠标指针在窗口的 X 坐标、Y 坐标 |
pageX/pageY | 鼠标指针在文档的 X 坐标、Y 坐标 |
ctrlKey、altKey、shiftKey | 是否按下了Ctrl 、Alt 、Shift 按键,bool值 |
metaKey | Mac中的 Cmd,同window的Ctrl |
relatedTarget | 次要(关联)目标,鼠标移入/出中使用,表示上一个target |
鼠标点击位置动画示例:codepen
<style>
.mpoint {
position: absolute;
padding: 0; margin: 0;
width: 200px; height: 200px;
background-color: #dda427;
border-radius: 50%;
animation: click 1s;
}
@keyframes click {
0% { transform: scale(0, 0); opacity: 0; }
30% { transform: scale(1, 1); opacity: 1; }
100% { transform: scale(0, 0); background-color: #7c20e4; opacity: 0; }
}
</style>
<script>
let cdiv = document.createElement('div');
//动画执行完后移除自身
cdiv.addEventListener('animationend', () => cdiv.remove());
window.addEventListener('click', (e) => {
document.body.append(cdiv);
cdiv.className = 'mpoint';
//定位圆圈的位置,为鼠标点坐标
cdiv.style.left = (e.clientX - cdiv.clientWidth / 2) + 'px';
cdiv.style.top = (e.clientY - cdiv.clientHeight / 2) + 'px';
});
</script>
2.3、键盘事件KeyboardEvent
键盘事件(event) | |
---|---|
keydown、keyup | 键盘按键按下、松开时触发 |
过时的keypress |
KeyboardEvent属性 | |
---|---|
code | 按键编码(KeyA、KeyA、F1、0、Shift),物理按键的准确编码,比较稳定 |
key | 按键值(A、a、F1、Digit0、ShiftLeft),正常看到的值,可能会随系统语言、输入环境变化 |
repeat | 按键是否被一直按住,bool。按住时会一直触发keydown |
ctrlKey、altKey、shiftKey | 是否按下了Ctrl 、Alt 、Shift 按键,bool值 |
metaKey | Mac中的 Cmd,同window的Ctrl |
03、表单事件
3.1、表单查找/取值
获取表单<form>
,<form name="formName">
除了元素查找还有如下方式
- 属性访问:
document.formName
, - forms属性:
document.forms
为文档中所有表单集合。
<form name="loginForm"><input type="text"></form>
<script>
document.loginForm;
document.forms.loginForm;
document.forms['loginForm'];
document.forms[0];
</script>
获取表单元素:
form.name
form.elements
集合,不用管元素的层级- form.elements.name,单个元素
- form.elements['name'],元素名为
name
的集合,组合元素使用。
- 子表单
fieldset.elements
表单和表单元素的双向引用:
表单元素取值:input.value,<input>
表单元素大部分都是value
取值/赋值,注意下面的:
- input.checked,单选
radio
、多选checkbox
通过checked
取值/赋值,多个需要遍历取值。 - textarea.value,️注意多行文本
<textarea>
是通过value
取值,而不是innerHTML
。 - 下拉框select:select.options =
<option>
的子元素的集合- 单选:
select.value
、select.selectedIndex
- 多选:遍历
options
取值,Array.from(select.options).filter(op=>op.select).map(op=>op.value);
- 单选:
提交表单:
- document.loginForm.submit():表单的
submit()
方法提交,完全自主控制,推荐食用。 - submit按钮+事件onclick=return 校验函数():校验函数校验表单数据,返回true提交表单,否则不提交
<button type="submit" onclick="return canSubmit()">
- submit按钮+form的事件onsubmit=return 校验函数():功能和用法基本同上。
<form name="fuser" id="fuser" action="" method="post">
姓名:<input name="userName" type="text" title="请输入用户名" /><br />
密码:<input name="userPwd" type="password" title="请输入密码" /><br />
生日:<input name="userBirthday" type="date" value="2021-10-11" /><br />
性别:<input name="sex" id="usex1" type="radio" value="男" checked=true /><label for="usex1">男</label>
<input name="sex" id="usex2" type="radio" value="女" /><label for="usex2">女</label>
<input name="sex" id="usex3" type="radio" value="其他" /><label for="usex3">其他</label><br />
爱好:<input id="uint1" name="interest" type="checkbox" value="运动" /><label for="uint1">运动</label>
<input id="uint2" name="interest" type="checkbox" value="学习" /><label for="uint2">学习</label>
<input id="uint3" name="interest" type="checkbox" value="看书" /><label for="uint3">看书</label>
<input id="uint4" name="interest" type="checkbox" value="躺着" /><label for="uint4">躺着</label><br />
学历:<select id="education" name="education">
<option value="大专">大专</option>
<option value="本科">本科</option>
<option value="研究生">研究生</option>
</select><br />
<button type="button" onclick="getData()">获取数据</button>
</form>
<script>
var form = document.fuser;
function getData() {
var form = document.fuser;
var userData = {};
userData.userName = form.userName.value;
userData.userPwd = form.userPwd.value;
userData.userBirthday = form.userBirthday.value;
//单选、多选,注意设置name、value值,遍历取值
userData.sex = Array.from(document.getElementsByName('sex'))
.filter(n => n.checked)[0]?.value
userData.interest = Array.from(document.getElementsByName('interest'))
.filter(n => n.checked).map(n=>n.value).join();
//下拉框取值
userData.education = form.education.value;
userData.education = form.education.options[form.education.selectedIndex].value;
console.log(JSON.stringify(userData));
};
getData();
</script>
3.2、表单事件
表单事件(event) | |
---|---|
blur(event)、focusout() | 元素失去焦点,blur不会冒泡 (blue /blɜːr/ 模糊 /不乐/) |
focus、focusin | 元素获取焦点时触发,focus不会冒泡 |
from.submit | 提交表单form时触发,可用于表单校验 |
change | 值发生变化时触发,文本框是在值变化且失去焦点是才触发 |
input | 输入值改变时触发。event.preventDefault()无法阻止,因为已经改变了 |
方法-聚焦 | |
elem.focus() | 设置元素获得焦点 |
elem.blur() | 设置元素失去焦点 |
可编辑单元格的表格示例:codepen
️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀
JavaScript入门⑧-事件总结大全的更多相关文章
- JavaScript onkeydown事件入门实例(键盘某个按键被按下)
JavaScript onkeydown 事件 用户按下一个键盘按键时会触发 onkeydown 事件.与 onkeypress事件不同的是,onkeydown 事件是响应任意键按下的处理(包括功能键 ...
- JavaScript入门篇 编程练习
编程挑战 一.定义"改变颜色"的函数 提示: obj.style.color obj.style.backgroundColor 二.定义"改变宽高"的函数 提 ...
- 慕课网JavaScript入门篇课程笔记
1.js注释很重要 单行注释,在注释内容前加符号 “//”. <script type="text/javascript"> document.write(" ...
- JavaScript入门基础
JavaScript基本语法 1.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=).算术运 ...
- Google Map JavaScript API V3 实例大全
Google Map JavaScript API V3 实例大全 基础知识 简单的例子 地理位置 语言 位置 坐标 简单的投影 事件 简单事件 关闭事件 多次添加事件 事件属性 控制 php禁用ui ...
- javascript入门视频第一天 小案例制作 零基础开始学习javascript
JavaScript 是我们网页设计师必备的技能之一.我们主要用javascript来写的是网页特效.我们从零基础开始学习javascript入门. 但是,好的同学刚开始不知道怎么学习,接触js,因此 ...
- JavaScript入门篇
记录一下在慕课网学习JavaScript的过程. 以下内容均来自慕课网. 传送:https://www.imooc.com/code/401 为什么学习JavaScript 1. 所有主流浏览器都支持 ...
- JavaScript入门--慕课网学习笔记
JAVASCRIPT—(慕课网)入门篇 我们来看看如何写入JS代码?你只需一步操作,使用<script>标签在HTML网页中插入JavaScript代码.注意, <script&g ...
- JavaScript入门几个概念
JavaScript入门几个概念 刚刚入门JavaScript的时候,搞懂DOM.BOM以及它们的对象document和window很有必要. DOM是为了操作文档出现的API,document是它的 ...
- javascript入门笔记3-dom
1.通过ID获取元素 document.getElementById("id") <!DOCTYPE HTML> <html> <head> & ...
随机推荐
- Git Review + Gerrit 安装及使用完成 Code-Review
转载自:https://cloud.tencent.com/developer/article/1010615 1.Code Review 介绍 Code Review 代码评审是指在软件开发过程中, ...
- Prometheus 监控报警系统 AlertManager 之邮件告警
转载自:https://cloud.tencent.com/developer/article/1486483 文章目录1.Prometheus & AlertManager 介绍2.环境.软 ...
- 欢迎来到ktq_cpp的cnblog
欢迎来到ktq_cpp的cnblog 初学html,可能排版有一些问题,望指教 我的洛谷博客 我的AtCoder账号
- 浅谈-动态路由之OSPF的理解
路由 在网络中,路由相当于就是一张地图,让路由器知道这个对应的IP数据包应该往哪端口.网段走:而这个"地图"我们称之为路由表,不同的目的IP路由表的下一个跳也不同,其生成方式有又有 ...
- HNOI2008GT考试
题目链接 考虑dp,f(i,j)表示做到了第i位(共n位),当前的后缀串与A1~Aj相匹配 接下来的方案数.转移的话枚举一个k=0~9表示这位选什么,如果选了以后,匹配的位置会改变到 j' ,j'可以 ...
- 齐博x1如果把万能表单直接插入到内容中去
很多时候,你创建了一个万能表单可能像下面这个情况,在文章中加一个链接叫别人点击填表,其实这个很不人性化,用户也容易忽略. 其实你完全可以像下面这样,把表单直接引用到文章中来.给用户更直观的感觉 那是如 ...
- SpringBoot自动配置(装配)流程
源码分析 SpringBoot自动配置流程 首先,我们要了解在@SpringBootApplication注解的内部,还具有@EnableAutoConfiguration,@SpringBo ...
- 我的Spark学习笔记
一.架构设计 Driver根据用户代码构建计算流图,拆解出分布式任务并分发到 Executors 中去:每个Executors收到任务,然后处理这个 RDD 的一个数据分片子集 DAGSchedule ...
- 再来一次,新技术搞定老业务「GitHub 热点速览 v.22.44」
上上周 Next.js 新版本火了一把,这不本周热点趋势就有了一个 Next.js 13 新特性构建的网站,虽然它只是个实验性项目.同样可以搞定一些业务的还有 lama-cleaner,不过它并不是个 ...
- JetBrains新产品Aqua——自动化测试开发工具(抢鲜体验)
转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/9a093c88.html 你好,我是测试蔡坨坨. 随着行业内卷越来越严重,自动化测试已成为测试工程师的必备技能,谈及自动化测 ...