前言
本篇文章是我的读书笔记,这里我直接从事件开始的原因是我之前没有写博客,最近一段时间才开始。之前的JS笔记也都有写,如果有人想看,欢迎留言/私信,我会把之前的整理出来。
文章目录
JS 与 HTML 的交互是通过事件实现的
事件流
事件流就是描述接收事件的顺序。
IE支持事件的冒泡流,
Netscape Communicator
支持事件的捕获流。
别以为IE要停了就可以不学冒泡流了,DOM事件流是两者的结合哦!
1.事件冒泡
事件会从开始触发的元素逐层向上传播,现代的浏览器中的事件会一直冒泡到
window
对象
2.事件捕获
事件会从最不具体的节点元素传播到最具体的节点元素,所有浏览器都是从
window
对象开始捕获的,而
DOM2Events
规定是从
document
开始的。通常建议使用事件冒泡
3.DOM事件流
分为三个阶段:事件捕获、到达目标和事件冒泡。
事件捕获最先发生,为提前拦截事件提供可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。
实际的目标在捕获阶段不会接收到事件,因为在捕获阶段从
document
到html 再到body就结束了。下一阶段再div元素上发生触发事件 “到达目标" 阶段,通常事件处理时被认为是冒泡阶段的一部分。
现代浏览器都会在捕获阶段在事件目标上触发事件,所以会有两个机会处理事件。
事件处理程序
事件意味着用户或浏览器执行的某种动作。为响应事件而调用的函数被称为事件处理程序,通常函数名以
"on"
开头
1.HTML事件处理程序
提前说明:这种方法使用的不多
特定元素支持的每个事件都可以使用事件处理程序的名字以
HTML
属性的形式来指定。因为属性的值是
JS
代码,所以要注意转义问题。
//具体格式如下<input type="button" value="Click Me" onclick="console.log('Clicked')"/>
在该事件处理程序中可以调用在页面其他地方定义的脚本,可以访问全局作用域的一切。
以这种方式指定的事件处理程序,会创建一个函数来封装属性的值,函数有如下性质:
- 这个函数有一个特殊的局部变量
event
,其保存的是event
对象。函数的this
值相当于事件的目标元素。 - 其作用域链被扩展了。
document
和元素自身的成员都可以被当成局部变量访问,这是通过this
实现的function(){with(document){with(this){//属性值}}}//所以事件处理程序可以直接通过属性名访问自己的属性值。
但这种指定事件处理程序有一些问题:
- 时机问题。事件处理程序可能会在元素和用户已经交互后才会运行到,即事件处理程序写在了元素的后面。这时就会报错,所以用此方法注意
js
代码的位置,可以用try/catch
封装 - 事件处理程序的作用域链的扩展在不同的浏览器中会有不同的结果。因为不同的
js
引擎中标识符解析规则存在差异。 HTML
和JS
有强耦合,修改代码比较麻烦
2.DOM0事件处理程序
这种方法使用的更多
这种方法是传统方法,即把一个函数赋值给一个事件处理程序属性,要使用
js
指定事件处理程序,必须先取得要操作对象的引用
let btn = document.getElementById("myBtn");
然后把这个属性赋值为一个函数即可
//每个元素都有通常小写的事件处理程序属性
btn.onclick=function(){
console.log("Clicked");};
注:上面的代码在运行之后才会给事件处理程序赋值,如果在页面中上面的代码出现在按钮之后,可能出现没有反应的情况
事件处理程序会在元素的作用域中运行,即
this
等于元素。可以使用
this
引用元素本身和访问元素的任何属性和方法
以这种方式添加事件处理程序是注册在事件流的冒泡阶段。通过将事件处理程序属性的值设置为
null
,可以移除通过
DOM0
方式添加的事件处理程序
3.DOM2事件处理程序
DOM2Events
为事件处理程序的赋值和移除定义了两个方法:
addEventListener()
和
removeEventListener()
。
这两个方法的参数一致:事件名、事件处理函数和一个布尔值。
true
表示在捕获阶段调用事件处理程序,
false
(默认)表示在冒泡阶段调用。所有
DOM
节点都有这两种方法。
//用法let btn = document.getElementById("myBtn");lethandler=function(){
console.log(this.id);}
btn.addEventListener("click", handler,false);
btn.removeEventListener("click", handler,false);
使用此方式的优势可以为一个事件添加多个事件处理程序,
DOM0
只能添加一个。
注:使用这两种方法时不建议添加匿名函数,因为移除事件处理程序时必须保证和添加时的参数值是一样的,匿名函数没有名字所以无法保证相同,就无法移除。
大多情况都会选择将事件处理程序添加到事件流的冒泡阶段,主要原因是跨浏览器兼容性好。放到捕获阶段通常用于拦截事件。
4.跨浏览器事件处理程序
由于
IE
不久就会停用,所以可以不考虑兼容
IE
代码如下:
var EventUtil ={addHandler:function(element, type, handler){if(element.addEventListener)
element.addEventListener(type, handler,false);else
element["on"+ type]= handler;}removeHandler:function(element, type, handler){if(element.addEventListener)
element.removeEventListener(type, handler,false);else
element["on"+ type]=null;}};
事件对象
在
DOM
中发生事件时,所有相关信息都会被收集并存储在一个名为
event
的对象中。同样不看
IE
,所以下面说的都是
DOM
事件对象。
event
对象在事件处理程序执行完毕后,就会被销毁。
DOM事件对象
event
对象是传给事件处理程序的唯一参数,不管是
DOM0
还是
DOM2
都会传入这个对象。通过
HTML
属性指定的事件处理程序,同样可以使用。
不同事件生成的事件对象会包含不同的属性和方法,但也有一些公共的属性和方法。如下:
this、currentTarget 和 target的区别
在事件处理程序内,
this
对象始终等于
currentTarget
,
target
只包含事件的实际目标。如果事件处理程序直接添加到实际的目标(比如,将点击事件处理程序直接添加到一个按钮上)这时这三个值都一样的。
如果没有添加到按钮上,而是添加到其父级节点上,那么
target
就和其他两个不一样了。
target
属性等于按钮,但按钮没有注册事件处理程序,所以事件会冒泡到其父级节点上。
this
和
currentTarget
都等于父级节点。
type属性
type
属性在处理程序处理多个事件时很有用,比如:
let btn = document.getElementById("mybtn");lethandler=function(event){switch(event.type){case"click"://点击事件
console.log("Clicked");break;case"mouseover"://鼠标在其上方事件
event.target.style.backgroundColor ="red";break;case"mouseout"://鼠标移走事件
event.target.style.backgroundColor ="";break;}};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
preventDefault()方法
用于阻止特定事件的默认动作。任何可以使用此方法取消默认行为的事件,其事件对象
cancelable
属性都会设置为
true
let link = document.getElementById("mylink");
link.onclick=function(event){
event.preventDefalult();};
stopPropagation()方法
用于立即阻止事件流在DOM结构中传播,取消后续的事件捕获或冒泡。
let link = document.getElementById("mylink");
link.onclick=function(event){
console.log("Clicked");
event.stopPropagation();};
document.body.onclick=function(event){
console.log("body clicked");};//Clicked//不会输出body clicked,因为取消了冒泡
eventPhase属性
用于确定事件流当前所处的阶段。
- 捕获阶段:1
- 目标上:2
- 冒泡阶段:3
结语
事件的内容有点多,先讲到这里,后面是关于事件的类型、事件的委托和模拟事件,我们下次再说~~~
阅读的文章是《JavaScript高级程序设计(第四版)》
版权归原作者 聆听逝去的流 所有, 如有侵权,请联系我们删除。