JavaScript入门系列目录

01、事件基础

1.1、事件简介

事件Event)是JavaScript的心脏,触发各种交互,让网页动起来。事件是浏览器网页可以监测到的行为,如页面加载、鼠标点击、键盘按键等。在这些事件中可以自定义事件处理程序,用于实现各种业务需求。

事件对象的继承关系:

常见的事件类型、事件如下:

鼠标事件(event)
click(event) 点击触发,通常是鼠标左键在一个元素上被按下并放开时
dblclick 双击触发事件
contextmenu 鼠标右键点击触发
mousedownmouseup 鼠标按下、弹起时触发
mousemove 鼠标在元素上移动时触发
onmouseovermouseout 鼠标移入、移出元素区域时触发
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):一般常用的是冒泡阶段,这更符合逻辑。

事件从目标元素上开始冒泡,逐级向上春波,直到根节点。几乎所有事件都会冒泡,除了个别的,如blurfocus没有冒泡。

<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 鼠标右键点击触发
mousedownmouseup 鼠标按下、弹起时触发
mousemove 鼠标在元素上移动时触发
onmouseovermouseout 鼠标移入、移出元素区域时触发
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 是否按下了CtrlAltShift按键,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>

点击查看【codepen】

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 是否按下了CtrlAltShift按键,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.valueselect.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入门⑧-事件总结大全的更多相关文章

  1. JavaScript onkeydown事件入门实例(键盘某个按键被按下)

    JavaScript onkeydown 事件 用户按下一个键盘按键时会触发 onkeydown 事件.与 onkeypress事件不同的是,onkeydown 事件是响应任意键按下的处理(包括功能键 ...

  2. JavaScript入门篇 编程练习

    编程挑战 一.定义"改变颜色"的函数 提示: obj.style.color obj.style.backgroundColor 二.定义"改变宽高"的函数 提 ...

  3. 慕课网JavaScript入门篇课程笔记

    1.js注释很重要 单行注释,在注释内容前加符号 “//”. <script type="text/javascript"> document.write(" ...

  4. JavaScript入门基础

    JavaScript基本语法 1.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=).算术运 ...

  5. Google Map JavaScript API V3 实例大全

    Google Map JavaScript API V3 实例大全 基础知识 简单的例子 地理位置 语言 位置 坐标 简单的投影 事件 简单事件 关闭事件 多次添加事件 事件属性 控制 php禁用ui ...

  6. javascript入门视频第一天 小案例制作 零基础开始学习javascript

    JavaScript 是我们网页设计师必备的技能之一.我们主要用javascript来写的是网页特效.我们从零基础开始学习javascript入门. 但是,好的同学刚开始不知道怎么学习,接触js,因此 ...

  7. JavaScript入门篇

    记录一下在慕课网学习JavaScript的过程. 以下内容均来自慕课网. 传送:https://www.imooc.com/code/401 为什么学习JavaScript 1. 所有主流浏览器都支持 ...

  8. JavaScript入门--慕课网学习笔记

     JAVASCRIPT—(慕课网)入门篇 我们来看看如何写入JS代码?你只需一步操作,使用<script>标签在HTML网页中插入JavaScript代码.注意, <script&g ...

  9. JavaScript入门几个概念

    JavaScript入门几个概念 刚刚入门JavaScript的时候,搞懂DOM.BOM以及它们的对象document和window很有必要. DOM是为了操作文档出现的API,document是它的 ...

  10. javascript入门笔记3-dom

    1.通过ID获取元素 document.getElementById("id") <!DOCTYPE HTML> <html> <head> & ...

随机推荐

  1. Redis可视化工具(支持ssh链接)

    1.Redis Desktop Manager RedisDesktopManager,简称RDM,这是一款很出名的Redis可视化管理工具,支持Windows,Mac,Ipad,LInux 开源地址 ...

  2. 第五章:Admin管理后台 - 3:Admin文档生成器

    Django的admindocs应用可以从模型.视图.模板标签等地方获得文档内容. 一.概览 要激活admindocs,请按下面的步骤操作: 在INSTALLED_APPS内添加django.cont ...

  3. nginx日志输出配置json格式

    修改nginx配置文件 http { include mime.types; default_type application/octet-stream; charset utf-8; # 原有日志格 ...

  4. 浏览器的 JavaScript 控制台功能调试vue

    原始显示结果: 调试其中一个变量的值: 页面上呈现出调试后的效果了

  5. (四)JPA - JQPL 实现增删改查

    (一)JPA的快速入门 建议在需要使用时,看看之前的文章,先把环境搭起来. 5.JPQL JPQL和SQL 1.JPQL和SQL很像,查询关键字都是一样的 2.唯一的区别是:JPQL是面向对象的 JP ...

  6. Spring Cloud Consul 入门指引

    1 概述 Spring Cloud Consul 项目为 Spring Boot 应用程序提供了与 Consul 的轻松集成. Consul 是一个工具,它提供组件来解决微服务架构中一些最常见的挑战: ...

  7. 微信小程序之发起请求

    wx.request({ url: api.api + '/weChat/api/user/myAunt', // 仅为示例,并非真实的接口地址 data: {}, method: 'GET', he ...

  8. vue3的Async Components异步组件

    前言: 当我们的项目达到一定的规模时,对于某些组件来说,我们并不希望一开始全部加载,而是需要的时候进行加载:这样的做得目的可以很好的提高用户体验. 传统方式引入组件如下,这样会一次先加载所以组件 先在 ...

  9. SpringBoot-JavaMailSender接口实战

    相信使用过Spring的众多开发者都知道Spring提供了非常好用的JavaMailSender接口实现邮件发送,在Spring Boot的Starter模块中也为此提供了自动化配置. 下面通过实例来 ...

  10. Java学习之路:HelloWorld

    2022-10-08 16:13:57 HelloWorld   1. 随便新建一个文件夹,存放代码   2. 新建一个Java文件 文件后缀名为.java hello.java 注意:系统没有显示后 ...