鼠标事件:
click
—— 当鼠标点击一个元素时(触摸屏设备会在点击时生成)。dbclick
——在短时间内双击同一元素后触发。如今已经很少使用了contextmenu
—— 当鼠标右键点击一个元素时。mouseover
/ mouseout
—— 当鼠标指针移入/离开一个元素时。mousedown
/ mouseup
—— 当在元素上按下/释放鼠标按钮时。mousemove
—— 当鼠标移动时。键盘事件:
keydown
和 keyup
—— 当按下和松开一个按键时。表单(form)元素事件:
submit
—— 当访问者提交了一个 <form>
时。focus
—— 当访问者聚焦于一个元素时,例如聚焦于一个 <input>
。Document 事件:
DOMContentLoaded
—— 当 HTML 的加载和处理均完成,DOM 被完全构建完成时。CSS 事件:
transitionend
—— 当一个 CSS 动画完成时语法:element.addEventListener(event, handler[, options]);
参数:
event
:事件名handler
:处理程序once
:如果为 true
,那么会在被触发后自动删除监听器。capture
:事件处理的阶段,捕获于冒泡false/true
,它与 {capture: false/true}
相同。passive
:如果为 true
,那么处理程序将不会调用 preventDefault()
handler
也可以是对象/类,只要它包含对象处理程序handleEvent
,必须是这个命名。当 addEventListener
接收一个对象作为处理程序时,在事件发生时,它就会调用 obj.handleEvent(event)
来处理事件<button id="elem">Click me</button> <script> let obj = { handleEvent(event) { alert(event.type + " at " + event.currentTarget); } }; elem.addEventListener('click', obj); </script>
element.removeEventListener(event, handler[, options]);
当事件发生时,浏览器会创建一个 event
对象,将详细信息放入其中,并将其作为参数传递给处理程序:
event.type
——事件类型event.currentTarget
——处理事件的元素。这与 this
相同,除非处理程序是一个箭头函数,或者它的 this
被绑定到了其他东西上,之后我们就可以从 event.currentTarget
获取元素了event.clientX / event.clientY
——指针事件(pointer event)的指针的窗口相对坐标冒泡(bubbling):(目标元素→父元素)当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序
冒泡中的event.target
:
父元素上的处理程序始终可以获取事件实际发生位置的详细信息。引发事件的那个嵌套层级最深的元素被称为目标元素,可以通过event.target
访问。它与 this
(也是event.currentTarget
)之间是有区别的:
event.target
—— 是引发事件的“目标”元素,它在冒泡过程中不会发生变化。this
—— 是“当前”元素,其中有一个当前正在运行的处理程序停止冒泡:
冒泡事件从目标元素开始向上冒泡。通常,它会一直上升到 <html>
,然后再到 document
对象,有些事件甚至会到达 window
,它们会调用路径上所有的处理程序。但是任意处理程序都可以决定事件已经被完全处理,并停止冒泡。用于停止冒泡的方法是 event.stopPropagation()
。
<body onclick="alert(`the bubbling doesn't reach here`)"> <button onclick="event.stopPropagation()">Click me</button> </body>
通常,没有真正的必要去阻止冒泡
捕获阶段(Capturing phase)—— 事件(从 Window)向下走近元素。
目标阶段(Target phase)—— 事件到达目标元素。
冒泡阶段(Bubbling phase)—— 事件从元素上开始冒泡
表格中点击 <td>
的图片时DOM传播过程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4DEHmJMa-1637770704979)(C:\Users\HeHao\AppData\Roaming\Typora\typora-user-images\image-20211119005232611.png)]
为了在捕获阶段捕获事件,我们需要将处理程序的 capture
选项设置为 true
:elem.addEventListener(..., {capture: true})
或elem.addEventListener(..., true)
apture
选项有两个可能的值:
false
(默认值),则在冒泡阶段设置处理程序。true
,则在捕获阶段设置处理程序。注意可以给事件click添加两个相同的方法,那么就又可以冒泡又可以捕获了
什么是事件委托
JavaScript事件委托也叫事件代理,实际上就是通过冒泡/捕获机制将一个元素的响应事件委托给另外一个元素,支持位同一个DOM注册多个同类型事件
事件委托的优点:
event
对象。有一个 event.preventDefault()
方法on<event>
(而不是 addEventListener
)分配的,那返回 false
也同样有效<a href="/" onclick="return false">Click here</a> <a href="/" onclick="event.preventDefault()">here</a>
addEventListener
的可选项 passive: true
向浏览器发出信号,表明处理程序将不会调用 preventDefault()
。
为什么需要这样做?移动设备上会发生一些事件,例如 touchmove
(当用户在屏幕上移动手指时),默认情况下会导致滚动,但是可以使用处理程序的 preventDefault()
来阻止滚动。因此,当浏览器检测到此类事件时,它必须首先处理所有处理程序,然后如果没有任何地方调用 preventDefault
,则页面可以继续滚动。但这可能会导致 UI 中不必要的延迟和“抖动”。passive: true
选项告诉浏览器,处理程序不会取消滚动。然后浏览器立即滚动页面以提供最大程度的流畅体验,并通过某种方式处理事件。对于某些浏览器(Firefox,Chrome),默认情况下,touchstart
和 touchmove
事件的 passive
为true
。
如果默认行为被阻止,那么 event.defaultPrevented
属性为 true
,否则为 false
。
click
—— 当鼠标点击一个元素时(触摸屏设备会在点击时生成)。dbclick
——在短时间内双击同一元素后触发。如今已经很少使用了contextmenu
—— 当鼠标右键点击一个元素时。mouseover
/ mouseout
—— 当鼠标指针移入/离开一个元素时。over、out、enter、leavemousedown
/ mouseup
—— 当在元素上按下/释放鼠标按钮时。mousemove
—— 当鼠标移动时。遵循 mousedown
→ mouseup
→ click
鼠标按键状态 | event.button |
---|---|
左键 (主要按键) | 0 |
中键 (辅助按键) | 1 |
右键 (次要按键) | 2 |
X1 键 (后退按键) | 3 |
X2 键 (前进按键) | 4 |
shift
、alt
、ctrl
、meta
shiftKey
:Shift
altKey
:Alt(或对于 Mac 是 Opt)
ctrlKey
:Ctrl
metaKey
:对于 Mac 是 Cmd
<button id="button">Alt+Shift+Click on me!</button> <script> button.onclick = function(event) { if (event.altKey && event.shiftKey) { alert('Hooray!'); } }; </script>
所有的鼠标事件都提供了两种形式的坐标:
相对于窗口的坐标:clientX
和 clientY
。
相对于文档的坐标:pageX
和 pageY
双击鼠标会有副作用,在某些界面中可能会出现干扰:它会选择文本。在这种情况下,最合理的方式是防止浏览器对 mousedown
进行操作。
**防止复制:**如果我们想禁用选择以保护我们页面的内容不被复制粘贴,那么我们可以使用另一个事件:oncopy
。
<div oncopy="alert('Copying forbidden!');return false"> Dear user, The copying is forbidden for you. If you know JS or HTML, then you can get everything from the page source though. </div>
指针事件 | 类似的鼠标事件 |
---|---|
pointerdown | mousedown |
pointerup | mouseup |
pointermove | mousemove |
pointerover | mouseover |
pointerout | mouseout |
pointerenter | mouseenter |
pointerleave | mouseleave |
pointercancel | - |
gotpointercapture | - |
lostpointercapture | - |
指针事件具备和鼠标事件完全相同的属性,包括 clientX/Y
和 target
等,以及一些其他属性:
pointerId
—— 触发当前事件的指针唯一标识符。
浏览器生成的。使我们能够处理多指针的情况,例如带有触控笔和多点触控功能的触摸屏
pointerType
—— 指针的设备类型。必须为字符串,可以是:“mouse”、“pen” 或 “touch”。
我们可以使用这个属性来针对不同类型的指针输入做出不同响应。
isPrimary
—— 当指针为首要指针(多点触控时按下的第一根手指)时为 true
。
有些指针设备会测量接触面积和点按压力(例如一根手指压在触屏上),对于这种情况可以使用以下属性:
width
—— 指针(例如手指)接触设备的区域的宽度。对于不支持的设备(如鼠标),这个值总是 1
。height
—— 指针(例如手指)接触设备的区域的长度。对于不支持的设备,这个值总是 1
。pressure
—— 触摸压力,是一个介于 0 到 1 之间的浮点数。对于不支持压力检测的设备,这个值总是 0.5
(按下时)或 0
。tangentialPressure
—— 归一化后的切向压力(tangential pressure)。tiltX
, tiltY
, twist
—— 针对触摸笔的几个属性,用于描述笔和屏幕表面的相对位置。大多数设备都不支持这些属性,因此它们很少被使用。如果你需要使用它们, 可以翻阅规范文档
pointercancel
事件将会在一个正处于活跃状态的指针交互由于某些原因被中断时触发。也就是在这个事件之后,该指针就不会继续触发更多事件了。自定义拖放事件必须阻止浏览器默认指针事件!可以通过JSelem.ondragstart = () => false
或者CSS的elem { touch-action: none }
导致指针中断的可能原因如下:
elem.setPointerCapture(pointerId)
—— 将给定的 pointerId
绑定到 elem
。在调用之后,所有具有相同 pointerId
的指针事件都将 elem
作为目标(就像事件发生在 elem
上一样),无论这些 elem
在文档中的实际位置是什么。
绑定会在以下情况下被移除:
pointerup
或 pointercancel
事件出现时,绑定会被自动地移除。elem
被从文档中移除后,绑定会被自动地移除。elem.releasePointerCapture(pointerId)
被调用,绑定会被移除scroll
事件允许对页面或元素滚动作出反应。我们可以在这里做一些有用的事情。
防止滚动:**不能通过在 onscroll
监听器中使用 event.preventDefault()
来阻止滚动,因为它会在滚动发生之后才触发。但可以处理导致滚动的事件防止滚动**,例如在 pageUp 和 pageDown 的 keydown
事件上,使用 event.preventDefault()
来阻止滚动
启动滚动:方法很多,使用 CSS 的 overflow
属性更加可靠
document.forms
的成员。这就是所谓的“命名的集合”,既是被命名了的,也是有序的。我们既可以使用名字,也可以使用在文档中的编号来获取表单。document.forms.my - name="my" 的表单 document.forms[0] - 文档中的第一个表单
form.elements[name]
将会是一个集合,例如:<form> <input type="radio" name="age" value="10"> <input type="radio" name="age" value="20"> </form> <script> let form = document.forms[0]; let ageElems = form.elements.age; alert(ageElems[0]); // [object HTMLInputElement] </script>
对于任何元素,其对应的表单都可以通过 element.form
访问到。因此,表单引用了所有元素,元素也引用了表单。
反向引用:对于任何元素,其对应的表单都可以通过 element.form
访问到。因此,表单引用了所有元素,元素也引用了表单。
input和textarea:
我们可以通过 input.value
(字符串)或 input.checked
(布尔值)来访问复选框(checkbox)中的它们的 value
。
select和option:
一个 <select>
元素有 3 个重要的属性:
select.options
—— <option>
的子元素的集合,select.value
—— 当前所选择的 <option>
的 value
,select.selectedIndex
—— 当前所选择的 <option>
的编号。它们提供了三种为 <select>
设置 value
的不同方式:
<option>
元素,并将 option.selected
设置为 true
。select.value
设置为对应的 value
。select.selectedIndex
设置为对应 <option>
的编号。<select id="select"> <option value="apple">Apple</option> <option value="pear">Pear</option> <option value="banana">Banana</option> </select> <script> // 所有这三行做的是同一件事 select.options[2].selected = true; select.selectedIndex = 2; select.value = 'banana'; </script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZTjyOp1O-1637770704982)(C:\Users\HeHao\AppData\Roaming\Typora\typora-user-images\image-20211124234827771.png)]
事件
elem.onfocus = func
elem.onblur = func
方法
允许在任何元素上聚焦:tabindex
默认情况下,很多元素不支持聚焦。任何浏览器中focus/blur
都支持这些用户可以交互的元素如<button>
,<input>
,<select>
,<a>
等。但一些诸如<div>
、<span>
等元素却不能,但是我们可以使用HTML-特性(attribute)tabindex
可以改变这种情况。任何具有 tabindex
特性的元素,都会变成可聚焦的。该特性的 value
是当使用 Tab(或类似的东西)在元素之间进行切换时,元素的顺序号。tabindex
的值决定Tab键跳转的顺序
委托
focus
和 blur
事件不会向上冒泡。目前又两个解决方案:
focusin
和 focusout
事件 —— 与 focus/blur
事件完全一样,只是它们会冒泡。但必须使用elem.addEventListener
来分配它们,而不是 on<event>
change
事件。对于文本输入框,当其失去焦点时,就会触发 change
事件。对于其它元素:select
,input type=checkbox/radio
,会在选项更改后立即触发 change
事件。input
事件,无法使用event.preventDefault()
阻止事件发生event.preventDefault()
来中止行为。event.clipboardData
属性可以用于读/写剪贴板。提交表单时,会触发 submit
事件,它通常用于在将表单发送到服务器之前对表单进行校验,或者中止提交,并使用 JavaScript 来处理表单
submit事件
提交表单主要有两种方式:
<input type="submit">
或 <input type="image">
input
字段中按下 Enter 键。这两个行为都会触发表单的 submit
事件。处理程序可以检查数据,如果有错误,就显示出来,并调用 event.preventDefault()
,这样表单就不会被发送到服务器了。
submit方法
如果要手动将表单提交到服务器,我们可以调用 form.submit()
。这样就不会产生 submit
事件。
属性可以用于读/写剪贴板。
提交表单时,会触发 submit
事件,它通常用于在将表单发送到服务器之前对表单进行校验,或者中止提交,并使用 JavaScript 来处理表单
submit事件
提交表单主要有两种方式:
<input type="submit">
或 <input type="image">
input
字段中按下 Enter 键。这两个行为都会触发表单的 submit
事件。处理程序可以检查数据,如果有错误,就显示出来,并调用 event.preventDefault()
,这样表单就不会被发送到服务器了。
submit方法
如果要手动将表单提交到服务器,我们可以调用 form.submit()
。这样就不会产生 submit
事件。