【Day24】派一个Spy到网页中窃听—事件监听

先来说说什麽是「事件」呢?

举个例子:看到红灯,就踩刹车!

「看到红灯」就是事件;「踩刹车」就是事件发生後所采取的行动。而在网页上所发生的事件,可能是使用者滑鼠点击、滑鼠移入、滚动浏览器卷轴、改变视窗大小…等等。

浏览器载入网页时,会把所有的JavaScript程序码载入,但是并不是所有程序码都会马上执行,有些必须等到「事件发生」,才会执行相对应的程序码,例如,「按下按钮」,跳出「对话框」。「按下按钮」是事件(Event),「跳出对话框」就是执行相对应的程序码(Event Handler)。

当然你必须要把监听的事件(Event)跟你要执行的程序码(Event Handler)绑定在一起,事件发生时两者才会连动。

目前绑定的方法有:

  • 由网页上HTML元素上绑定on-event处理器
  • 利用DOM API所提供的on-event处理器来绑定

在网页上HTML元素上绑定on-event处理器

在HTML元素上透过「on + 事件名称」来绑定事件,只要事件被触发,就会执行JavaScript。

<button id="btn" onclick="alert('降龙十八掌之亢龙有悔')">点击出招</button>

在早期都是透过这种方式绑定事件,但随着观念的进化,这种「侵入式的写法」容易造成资安漏洞,也不符合「关注点分离」,由HTML负责架构与内容,JavaScript负责互动的观念。现在比较少用这种绑定事件的方式了。

利用DOM API所提供的on-event处理器来绑定

也可以在JavaScript中藉由document.getElementById()或document.querySelector()选取HTML元素当节点,然後将on-event绑定在选取的节点上。

<button id="btn">点击出招</button>
//选取节点
let btn = document.getElementById('btn');
//将on-event绑定在事件上
btn.onclick = function(){
	alert('降龙十八掌之见龙在田');
};

如果希望HTML一载入浏览器,JavaScript就自动执行,可以这样写:

window.onload = function(){
	alert('飞雪连天射白鹿,笑书神侠倚碧鸳');
}

事件监听

为了要侦测使用者对网页所做的行为,如果可以在网页中埋伏一个间谍,监看使用者是否有对指定的元素做出设定好的动作,如果有的话,就给予相对的回应,这样就会方便得多。

那该如何来做事件监听呢?基本上「事件监听」长成这个样子:

HTML元素节点.addEventListener('事件名称',事件处理器,boolean值)

「事件名称」指的是使用者对绑定的HTML元素节点所做的事情,例如点击(click)、滑鼠移入(mouseenter)…等事件。

「事件处理器」(Event Handler)指的是事件发生时,要叫用的function()。

布林值(boolean),false代表事件冒泡(Event Bubbling),而true代表事件捕捉(Event Capturing)。这是甚麽意思呢?

事件冒泡(Event Bubbling):由启动事件的元素节点开始,向外层传递。

事件捕捉(Event Capturing):由最外层开始,一层一层找到启动事件的元素节点。

<!DOCTYPE html>
<html>
<head>
	<title>标题</title>
</head>
<body>
	<div>点我--隔山打牛--点我</div>
</body>

事件触发的传递顺序会是:

  1. <div>点我--隔山打牛--点我</div>
  2. <body>
  3. <html>
  4. document

因为<div>点我--隔山打牛--点我</div>也是在<body>的范围中,所以点击它的同时也会传递到<body>,跟着也会传到<html>与document。这种click事件一层一层往上依序被触发,就是「事件冒泡」机制。

而「事件捕获」传递的顺序则相反,同样是点击<div>点我--隔山打牛--点我</div>,但是传递顺序却如下:

  1. document
  2. <html>
  3. <body>
  4. <div>点我--隔山打牛--点我</div>

讲解完事件绑定,来看一下事件绑定的简单例子:

<button id="btn">用滑鼠点穴</button>
let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
	alert('脚麻袂冻行');
},false)

而且同元素的同一事件可以重复指定addEventListener()

let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
	alert('脚麻袂冻行');
},false)

btn.addEventListener('click',function(){
	alert('快吃循力宁');
},false)

如果是on-event的方法如果重复绑定的话,则只会出现最後一个绑定的事件。

<input type="button" onclick = "alert('见龙在田')" value="行内绑定">
<!-- 使用on-event绑定 -->
<input type="button" class="btnOn" value="on-event点击">
<!-- 使用addEventListener绑定 -->
<input type="button" class="btnAdd" value="addEvent点击">
var elOn = document.querySelector('.btnOn');

elOn.onclick = function(){
  alert('on-1');
}
//虽然同一物件绑订了两个on事件处理器,但是只会出现最後一个on-2
elOn.onclick = function(){
  alert('on-2');
}

var elAdd = document.querySelector('.btnAdd');

elAdd.addEventListener('click',function(){
  alert('add点击1');
},false)
//同一物件绑订了两个addEventListener,两个绑定的事件处理器都会执行
elAdd.addEventListener('click',function(){
  alert('add点击2');
},false) 

那如果要解除addEventListener()绑定的事件,可以使用removeEventListener()。

HTML元素节点.addEventListener('事件名称',事件处理器,boolean值)

but,要注意的是「事件处理器」必须要指向同一个「实体」,在下面范例中指的是相同名称的function。

let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
	alert('脚麻袂冻行');
},false)
//爱到不能动,还有甚麽值得我心痛,没办法移除事件,因为指向不同实体
btn.removeEventListener('click',function(){
	alert('脚麻袂冻行');
},false)

要这麽做才行:

let btn = document.getElementById('btn');

let canNotMove = function() {
	alert('脚麻袂冻行');
}

btn.addEventListener('click', canNotMove, false);

btn.removeEventListener('click', canNotMove, false);

<<:  【Day13】[资料结构]-二元树Binary Tree

>>:  10 | WordPress 图片区块 Image Block | 双色调滤镜 (Duotone Filter)

IOS、Python自学心得30天 Day-14 H5与Pb模型档案

前言: 因为内存不足以在训练的时候存 SavedModel模型 所以我分离出来 以.h5档案先做训练...

day4 : k8s建置(下)

昨天成功的用terraform创建gcp的instance出来,也透过terraform自动的把in...

第3砍 - 不亮也光

烦恼着要开始上班了 菜鸟人生 Start?[Y/N] > N 今天还没进入正题 因为我们需要先...

【DAY 5】主管签名好难追怎麽办? Power Automate - 核准

哈罗 ~ 大家好 ~ 欢迎回来 ~ 相信征战职场的大家,一定会有个苦恼的问题,那就是每次老板签公文都...

D23 - 用 Swift 和公开资讯,打造投资理财的 Apps { 台股成交量实作.3 }

在 KLineViewController 开出的 volumeDataSet 会在 parent ...