红宝书阅读笔记!第九天_事件

390 阅读8分钟

JavaScript与HTML的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻,可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件。在传统软件工程领域,这个模型叫“观察者模式”,其能够做到页面行为与页面展示的分离。

事件流

事件流描述了页面接受事件的顺序。结果非常有意思,IE和网景开发团队提出了完全相反的事件流方案。IE将支持事件冒泡流,网景支持事件捕获流。

1.事件冒泡

图放在这里了,俺就不多说了。

2.事件捕获

没有找到红宝书的配图,不过就是上面的顺序反过来,所有的浏览器都是从window对象开始事件捕获,DOM2规定从document开始。

3.DOM事件流

DOM2Events规范规定事件流分为3个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。

事件处理程序

事件意味着用户或浏览器执行的某个动作。比如:单击(click)、加载(load)、鼠标悬停(mouseover)。为响应事件调用的函数被称为事件处理程序(或事件监听器)。事件处理程序的名字以'on'开头。

1.HTML事件处理程序

特定元素支持的每个事件 都可以使用 事件监听器的名字 以HTML属性 的形式来指定。当时这句话看了好久,所以帮忙加了断句,看不懂可以继续往下看,然后回来重新再读。此时属性的值必须是能够执行的JavaScript代码。

<input type='button' value='click me' onclick="console.log('clicked')"/>

这里也可以调用在页面其他地方定义的脚本,比如👇

<script>
	function showMessage(){
    	console.log('hello world');
    }
</script>
<input type='button' value='click me' onclick='showMessage()'/>

script代码也可以在外部定义,作为事件处理程序执行的代码可以访问全局作用域中的一切。

以这种方式指定的事件处理程序有一些特殊的地方。首先,会创建一个函数来封装属性的值。这个函数有一个特殊的局部变量event,其中保存的就是event对象。

------------------------分割线------------------------

用下面这种方式指定的事件处理程序有一些特殊的地方。首先,会创建一个函数来封装属性的值,这个函数有一个特殊的局部变量event,其中保存的就是event对象:

<!--输出'click'-->
<input type='button' value='click me' onclick="console.log('event.type')"/>

有了这个对象,就不用开发者定义额外的变量,也不用从包装函数的参数列表去获取了。这个函数中this值相当于事件的目标元素:

<!--输出'click me'-->
<input type='button' value='click me' onclick="console.log('this.value')">

此外,这个函数的作用域链也被扩展了,这个函数中,document和元素本身的成员都可以被当成局部变量来访问。这是通过with实现的:

function(){
	with(document){
            with(this){
        	//属性值
        }	
    }
}

别问,我也没怎么看懂😅

👇和前面的示例功能一样

<!--输出'click me'-->
<input type='button' value='click me' onclick="console.log('value')">
------------------------分割线------------------------P494这里真的看不大懂,跳过啦

HTML中指定事件处理程序中有一些问题:第一个问题是时机问题。有可能HTML元素已经显示在页面上,用于都已经交互了,但是事件监听器还无法执行。所以大多数HTML事件处理程序会封装在try/catch块中,以便在这种情况下静默失败。

<input type='button' value='click me' onclick=" try{showMessage ();} catch(ex) {}">

另一个问题是对事件处理程序作用域链的扩展在不同的浏览器中可能导致不同的结果。不同的JavaScript引擎中标识符解析的规则存在差异。

2.DOM0事件处理程序

在JavaScript中指定事件处理程序的传统方法是把一个函数赋值给(DOM元素的)一个事件处理程序属性。

每个元素(包括window和document)都有通常小写的事件处理程序属性,比如onclick。只要把这个属性赋值为一个函数即可👇

let btn = document.getElementById('myBtn');
btn.onclick = function(){
	console.log("Clicked");	
};

先从文档中取得按钮,然后给它的onclick事件监听器复制一个函数。

像这样使用DOM0方式为事件处理程序赋值时,所赋值函数被视为元素的方法。因此程序会在元素的作用域中运行,即this等于元素。

3.DOM2事件处理程序

DOM2 Events为事件处理程序的赋值和移除定义了两个方法:addEventListener()removeEventListener()。这两个方法暴露在所有的DOM节点上,他们接收3个参数:事件名、事件处理函数和一个布尔值,true表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事件监听器。

使用DOM2的优势是可以为一个事件添加多个事件监听器。

let btn = document.getElementById('myBtn');
let f = function(){
	pass;
};
btn.addEventListener('click',f,false);
btn.removeEventListener('click',f,false);

取消事件监听器时,要给remove传入和add一样的函数。

4.IE事件处理程序

5.跨浏览器事件处理程序

事件对象

在DOM中发生事件时,所有相关信息都会被收集并存储在一个名为event的对象中。这个对象包含了一系列的基本信息,比如导致事件的元素,发生的事件类型,以及可能与特定事件相关的任何其他数据。

1.DOM事件对象

在DOM合规的浏览器中,event对象是传给时间处理程序的唯一参数。👇

let btn = document.getElementById("myBtn");
btn.onclick = function(event){
	console.log (event.type); 	 //click
}

btn.addEventListener("click",(event) =>{
	console.log (event.type);	//click
},false);

❗这里是我找到比较全的梳理w3school

在事件处理程序内部,this对象始终等于currentTarget值,而target只包含事件的实际目标。

type属性在一个处理程序处理多个事件时很有用。

preventDefault()方法用于阻止特定事件的默认动作。任何可以通过preventDfault()取消默认行为的事件,其事件对象的cancelable属性都会设置为true。

stopPropagation()方法用于立即阻止事件流在DOM结构中传播,取消后续的事件捕获或冒泡。

eventPhase属性可用来确定事件流当前所处的阶段。👇

如果事件处理程序在捕获阶段被调用,则eventPhase等于1;

如果事件处理程序在目标上被调用,则eventPhase等于2;

如果事件处理程序在冒泡阶段被调用,则值为3.

2.IE事件对象

3.跨浏览器事件对象

事件类型

DOM3 Events定义了如下事件类型👇

⚪用户界面事件(UIEvent):涉及与BOM交互的通用浏览器事件。

⚪焦点事件(FocusEvent):在元素获得或失去焦点时触发。

⚪鼠标事件(MouseEvent):使用鼠标在页面上执行某些操作时触发。

⚪滚轮事件(WheelEvent):使用鼠标滚轮时触发。

⚪输入事件(InputEvent):像文档中输入文本时触发。

⚪键盘事件(KeyboardEvent):使用键盘在页面上执行某些操作时触发。

1.用户界面事件

我总觉得这里说的不全,如果我看完了整本书都没有讲到的话,我就回来补充

1.load事件

load事件会在整个页面加载完成后触发,可以通过两种方式指定load事件处理程序。

第一种是JavaScript方式,👇

window.addEventListener("load",(event) => {
	console.log("loaded!");
});

第二种指定load事件处理程序的方式是向<body>元素添加onload属性,👇:

<body onload="console.log('Loaded!')">

不过开发中,尽量使用第一种JavaScript的方式。

2.unload事件

unload事件一般是在一个页面导航到另外一个页面时触发,最常用于清理引用,以避免内存泄漏。

3.resize事件

当浏览器窗口被缩放到新高度或者宽度时,会触发resize事件,这个事件在window上触发,因此可以通过JavaScript在window上来指定事件处理程序。

window.addEventListener('resize',(event) => {
	console.log('resized');
});

4.scroll事件

2.焦点事件

blur:元素失去焦点时触发,不冒泡。

foucus:当元素获得焦点时触发,不冒泡。

foucusin:当元素获得焦点时触发,冒泡。

foucusout:当元素失去焦点时触发,冒泡。

3.鼠标和滚轮事件

click:在用户单击鼠标或按下回车。

dblclick:双击鼠标。

mousedown:按下鼠标任意键,键盘不行。

mouseenter:用户把鼠标光标从外部移到内部触发。不冒泡

mouseleave:用户把鼠标光标从内部移向外部触发。不冒泡

mousemove:鼠标光标在元素上移动时反复触发。

mouseout:用户把鼠标从一个元素移动到另一个元素上时触发。

mouseover:在用户把鼠标光标从元素外部移到元素内部时触发。不可以通过键盘

mouseup:在用户释放鼠标键时触发。

1.客户端坐标(clientX,clientY)

2.页面坐标(pageX,pageY)

3.屏幕坐标(screenX,screenY)

4.修饰键

5.相关元素

4.键盘与输入事件

到时候百度,然后看书。P518

内存与性能

1.事件委托

事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,利用click冒泡到document

2.删除事件处理程序

文章内容参考:JavaScript高级程序设计(第四版)

标题样式来自:juejin.cn/post/684490…

哪里写错了就联系我🐧:54269504