摘要:事件监听器可以被添加到节点上并在给定事件发生时触发。可以选择触发阶段冒泡捕获事件机制标准事件标准规定事件流包含三个阶段,分别为事件捕获阶段,目标阶段,事件冒泡阶段。返回其事件监听器触发该事件的元素。清理事务设置检查点的标志为。
前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。
前面我们已经基本掌握常规的语法语义,以及基本的使用方法。接下来我们讲深入进去了解其中内在的原理。
今天我们要讲什么?事件机制
事件对象(Event)
event loop
DOM (与事件的关系,看不看无所谓)DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的 API。DOM 是载入到浏览器中的文档模型,以节点树的形式来表现文档,每个节点代表文档的构成部分(例如:页面元素、字符串或注释等等)。
DOM 是万维网上使用最为广泛的 API 之一,因为它允许运行在浏览器中的代码访问文件中的节点并与之交互。节点可以被创建,移动或修改。事件监听器可以被添加到节点上并在给定事件发生时触发。
DOM 并不是天生就被规范好了的,它是浏览器开始实现JavaScript时才出现的。这个传统的 DOM 有时会被称为 DOM 0。现在, WHATWG 维护DOM现存标准。
-- MDN
既然 DOM 有版本,那么在他的环境上事件的支持也是有版本的。文档
DOM 事件(0 级)body.onclick 这种定义方式的。
不可以多次监听事件,因为是赋值的方式,下次赋值会覆盖。
只可以在冒泡阶段触发
DOM 事件(2 级)addEventListener 方式定义的。
可以多次监听,切按监听顺序执行回调(有序)
取消监听需要同一引用的函数。举个栗子
// 错误案例,两个方法不是同一引用,导致清除不掉 document.addEventListener("click", function(){}) document.removeEventListener("click", function(){}) // 正确案例,同一引用,可以清除。 function documentClick(){} document.addEventListener("click", documentClick) document.removeEventListener("click", documentClick)
可以选择触发阶段(冒泡&捕获) capture
事件机制标准事件:EMCAScript 标准规定事件流包含三个阶段,分别为事件捕获阶段,目标阶段,事件冒泡阶段。
先存个代码,之后的例子我们用这个例子。测试看我这里的 DEMO
click事件捕获阶段
捕获阶段:由外到内,触发规律为 html > body > a。
如果想在捕获阶段就触发,需要传入参数 {capture: true}
冒泡阶段:由内到外,触发规律为 a > body > html
这个阶段执行是 W3C 默认的,等价于 {capture: false}
图片来源-https://www.w3.org/TR/DOM-Lev...
事件的捕获阶段 > 处于目标阶段 > 事件的冒泡阶段 > 事件的默认行为
这里为什么要强调这个顺序呢?
因为默认行为是在最后面,所以我们都可以用 e.preventDefault() 来阻止。
基于上条的阻止默认事件。在移动端滑动时,阻止默认事件需要手动设置 passive 为 false。
passive: Boolean,设置为 true 时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。
我们真正单击的元素的事件触发不在冒泡和捕获阶段,而在目标阶段触发。 DEMO-冒泡&捕获阶段触发事件,可以看到,他是通过定义时的先后顺序来触发的。
事件对象(Event)Event 对象--mdn
事件对象(属性&方法)key | 类型 | 描述 |
---|---|---|
bubbles | boolean | 是否冒泡 |
cancelable | boolean | 是否可以取消的默认动作。 |
currentTarget | Element | 返回其事件监听器触发该事件的元素。(this 的真实指向) |
eventPhase | Intenger | 返回事件传播的当前阶段 |
target | Element | 返回触发此事件的元素。(事件的目标节点) |
timeStamp | Date | 触发的时间戳 |
type | String | 事件名称。 |
isTrusted | boolean | 该事件是否是浏览器生成(true 代表是,false 代表是开发人员创建 |
preventDefault | Function | 取消事件的默认行为在 cancelable=true 时有效 |
stopPropagation | Function | 取消事件的捕获或者冒泡行为在 bubbles=true 时有效 |
IE: event.cancelBubble=true; //阻止事件冒泡
IE: event.returnValue=false; //阻止事件的默认行为
获取事件 window.event
事件类型(分类、Event对象之类)DOM event 子类,根据不同的事件类型,返回的对象会有些许不同,比如 Mouse 类型的,就会有单击坐标之类的。 KeyboardEvent 之类的就会有按键之类的。
new 一个事件对象CustomEvent() --mdn
document.body.onclick=function(e){console.log(e)} var btn=document.body; var event= new CustomEvent("click"); btn.dispatchEvent(event);
其实这里我们可以自定义事件的名称,然后我们就可以实现一个发布订阅的功能。
document.addEventListener("bus", function(e) { console.log(e, e.detail) }); var event = new CustomEvent("bus", {detail: {LN_type: "lilnong.top"}}); document.dispatchEvent(event);event loop (事件循环)
首先,我们要牢记一件事情 js 是单线程
Event Loop 中文叫事件循环。是浏览器内部的一种机制,javaScript 单线程运行时如何不阻塞 UI。
Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈(栈采用的是后进先出的规则)等待主线程执行。
在 JavaScript 中,任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务(MicroTask)。
MacroTask(宏任务)、setTimeout、setInterval、setImmediate、I/O、UI Rendering。
异步任务会在有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。
Process.nextTick(Node独有)、Promise、MutationObserver
每个宏任务执行完毕后,会检查 microTask 队列是否有回调,会按照先入先出的规则执行,都执行完再执行宏任务,如此循环。
栈采用的是后进先出的规则,这里我们调用 a(),a() 内部会调用 aa(), aa() 内部又调用 aa()。
function a(){return aa()} function aa(){return aaa()} function aaa(){return 1}
a 进栈
aa 进栈
aaa 进栈
aaa 出栈
...
事件循环的进程模型选择任务队列中最先进入的任务,如果任务队列为空,则执行跳转到微任务(MicroTask)的执行步骤
任务设置为已选择任务
执行任务
任务设置为空
运行完成的任务从任务队列中删除
MicroTasks 步骤:
进入 MicroTask 检查点
设置 MicroTask 检查点标志为 true
当事件循环 MicroTask 不为空时:
选择最先进入队列的任务,
设置为已选择的任务
运行
将已经执行完成的 MicroTask 改变状态
移出 MicroTask。
清理IndexDB事务
设置 MicroTask 检查点的标志为false。
更新界面渲染。
返回第一步。
举个栗子(常问无聊题)console.log("script start"); setTimeout(function() { console.log("setTimeout"); }, 0); new Promise(function(reslove){ console.log("Promise-start") reslove(); }).then(function() { console.log("Promise-end"); }) console.log("script end");
结构应该没错
任务入栈(代码块)
console.log("script start"); 栈中,同步代码,直接输出
function() {console.log("setTimeout");} 入 MacroTask
new Promise 同步代码,执行
入栈 function(reslove){console.log("Promise-start");reslove();}
执行 console.log("Promise-start");
出栈
.then(function() {console.log("Promise-end");}) 进 MicroTask
console.log("script end"); 同步代码,输出
当前执行完出栈,判断 MicroTasks
执行 console.log("Promise-end");
完成所有 MicroTasks
渲染 UI
MacroTasks是否有数据?
执行 MacroTasks 中第一个。
console.log("setTimeout"); 输出。
异步事件(消息)DOM 事件
setTimeout
XHR
Promise
总结
事件机制
当前执行块
当前执行块的微任务队列
宏任务队列
Event 事件级别
addEventListener 要主要保存 function 的引用,用于解绑
队列,先进先出(想起了梗,吃多了拉)
堆栈,先进后出(想起了梗,吃多了吐)
触发阶段 捕获>目标>冒泡
Event 对象,针对不同的类型,有自己独特的属性。
微信公众号:前端linong 初级阶段文章目录前端培训-初级阶段(17) - 数据存储(cookie、session、stroage)
前端培训-初级阶段(13) - 正则表达式
前端培训-初级阶段(13) - 类、模块、继承
前端培训-初级阶段(13) - ECMAScript (内置对象、函数)
前端培训-初级阶段(13) - ECMAScript (语法、变量、值、类型、运算符、语句)
前端培训-初级阶段(13、18)
前端培训-初级阶段(9 -12)
前端培训-初级阶段(5 - 8)
前端培训-初级阶段(1 - 4)
资料前端培训目录、前端培训规划、前端培训计划
JavaScript系列----事件机制
事件参考--mdn
tasks-microtasks-queues-and-schedules
一次弄懂Event Loop(彻底解决此类面试问题) --光光同学-juejin
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/54051.html
摘要:事件监听器可以被添加到节点上并在给定事件发生时触发。可以选择触发阶段冒泡捕获事件机制标准事件标准规定事件流包含三个阶段,分别为事件捕获阶段,目标阶段,事件冒泡阶段。返回其事件监听器触发该事件的元素。清理事务设置检查点的标志为。 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/C...
摘要:前端最基础的就是。帮助从旧的事件方法转换,和。方法移除用绑定的事件处理程序。特定的事件处理程序可以被移除元素上提供事件名称,命名空间,处理函数。用于过滤器的触发事件的选择器元素的后代。事件触发模拟触发原生使用触发。 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS)...
摘要:前端最基础的就是。帮助从旧的事件方法转换,和。方法移除用绑定的事件处理程序。特定的事件处理程序可以被移除元素上提供事件名称,命名空间,处理函数。用于过滤器的触发事件的选择器元素的后代。事件触发模拟触发原生使用触发。 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS)...
阅读 1320·2021-09-28 09:43
阅读 3939·2021-09-04 16:41
阅读 1881·2019-08-30 15:44
阅读 3683·2019-08-30 15:43
阅读 745·2019-08-30 14:21
阅读 2009·2019-08-30 11:00
阅读 3278·2019-08-29 16:20
阅读 1874·2019-08-29 14:21