前端培训-中级阶段(2)-事件(event)事件冒泡,捕获

简介: 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。前面我们已经基本掌握常规的语法语义,以及基本的使用方法。接下来我们讲深入进去了解其中内在的原理。

今天我们要讲什么?


  1. 事件机制
  2. 事件对象(Event)
  3. event loop


DOM (与事件的关系,看不看无所谓)


DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的 API。DOM 是载入到浏览器中的文档模型,以节点树的形式来表现文档,每个节点代表文档的构成部分(例如:页面元素、字符串或注释等等)。

DOM 是万维网上使用最为广泛的 API 之一,因为它允许运行在浏览器中的代码访问文件中的节点并与之交互。节点可以被创建,移动或修改。事件监听器可以被添加到节点上并在给定事件发生时触发。

DOM 并不是天生就被规范好了的,它是浏览器开始实现JavaScript时才出现的。这个传统的 DOM 有时会被称为 DOM 0。现在, WHATWG 维护DOM现存标准。

既然 DOM 有版本,那么在他的环境上事件的支持也是有版本的。


DOM 事件(0 级)


body.onclick 这种定义方式的。


  1. 不可以多次监听事件,因为是赋值的方式,下次赋值会覆盖。
  2. 只可以在冒泡阶段触发


DOM 事件(2 级)


addEventListener 方式定义的。


  1. 可以多次监听,切按监听顺序执行回调(有序)
  2. 消监听需要同一引用的函数。举个栗子


// 错误案例,两个方法不是同一引用,导致清除不掉
    document.addEventListener('click', function(){})
    document.removeEventListener('click', function(){})
    // 正确案例,同一引用,可以清除。
    function documentClick(){}
    document.addEventListener('click', documentClick)
    document.removeEventListener('click', documentClick)


3.可以选择触发阶段(冒泡&捕获) capture


事件机制


标准事件:EMCAScript 标准规定事件流包含三个阶段,分别为事件捕获阶段,目标阶段,事件冒泡阶段。


先存个代码,之后的例子我们用这个例子。测试看我这里的 DEMO


<html onclick="alert('html')">
    <body onclick="alert('body')">
        <a onclick="alert('a')">click</a>
    </body>
</html>


事件捕获阶段


捕获阶段:由外到内,触发规律为 html > body > a

如果想在捕获阶段就触发,需要传入参数 {capture: true}


事件冒泡阶段


冒泡阶段:由内到外,触发规律为 a > body > html

这个阶段执行是 W3C 默认的,等价于 {capture: false}


事件执行顺序


a.png


图片来源-https://www.w3.org/TR/DOM-Lev...

事件的捕获阶段 > 处于目标阶段 > 事件的冒泡阶段 > 事件的默认行为


这里为什么要强调这个顺序呢?


  1. 因为默认行为是在最后面,所以我们都可以用 e.preventDefault() 来阻止。


  1. 基于上条的阻止默认事件。在移动端滑动时,阻止默认事件需要手动设置 passivefalse

passive: Boolean,设置为 true 时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。


  1. 我们真正单击的元素事件触发不在冒泡和捕获阶段,而在目标阶段触发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 时有效


  1. IE: event.cancelBubble=true; //阻止事件冒泡


  1. IE: event.returnValue=false; //阻止事件的默认行为


  1. 获取事件 window.event


事件类型(分类、Event对象之类)


DOM event 子类根据不同的事件类型,返回的对象会有些许不同,比如 Mouse 类型的,就会有单击坐标之类的。 KeyboardEvent 之类的就会有按键之类的。


bVbtYrr.webp.jpg


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 调用栈(执行栈),所有的任务都会被放到调用栈(栈采用的是后进先出的规则)等待主线程执行。


任务类别&任务队列(Task Queue)


JavaScript 中,任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务(MicroTask)。


MacroTask(宏任务)


<script>setTimeoutsetIntervalsetImmediateI/OUI Rendering


异步任务会在有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。


MicroTask(微任务)


Process.nextTick(Node独有)、PromiseMutationObserver

每个宏任务执行完毕后,会检查 microTask 队列是否有回调,会按照先入先出的规则执行,都执行完再执行宏任务,如此循环。


调用栈


栈采用的是后进先出的规则,这里我们调用 a()a() 内部会调用 aa(), aa() 内部又调用 aa()


function a(){return aa()}
function aa(){return aaa()}
function aaa(){return 1}


  1. a 进栈
  2. aa 进栈
  3. aaa 进栈
  4. aaa 出栈
  5. ...


事件循环的进程模型


  1. 选择任务队列中最先进入的任务,如果任务队列为空,则执行跳转到微任务(MicroTask)的执行步骤


  1. 任务设置为已选择任务


  1. 执行任务


  1. 任务设置为空


  1. 运行完成的任务从任务队列中删除


  1. MicroTasks步骤:


  1. 进入 MicroTask 检查点


       b.设置 MicroTask 检查点标志为 true


       c.当事件循环MicroTask不为空时:

  1. 选择最先进入队列的任务,
  2. 设置为已选择的任务
  3. 运行
  4. 将已经执行完成的 MicroTask 改变状态
  5. 移出 MicroTask


       d.清理IndexDB事务


       e.设置 MicroTask 检查点的标志为false。


  1. 更新界面渲染。


  1. 返回第一步。


举个栗子(常问无聊题)


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');


结构应该没错


  1. 任务入栈(代码块)


  1. console.log('script start'); 栈中,同步代码,直接输出


  1. function() {console.log('setTimeout');}MacroTask


  1. new Promise 同步代码,执行


  1. 入栈 function(reslove){console.log('Promise-start');reslove();}


  1. 执行 console.log('Promise-start');


  1. 出栈


  1. .then(function() {console.log('Promise-end');})MicroTask


  1. console.log('script end'); 同步代码,输出


  1. 当前执行完出栈,判断 MicroTasks


  1. 执行 console.log('Promise-end');


  1. 完成所有 MicroTasks


  1. 渲染 UI


  1. MacroTasks是否有数据?


  1. 执行 MacroTasks 中第一个。


  1. console.log('setTimeout'); 输出。


bVbtYWO.webp.jpg


异步事件(消息)


  1. DOM 事件
  2. setTimeout
  3. XHR
  4. Promise


总结


  1. 事件机制
  1. 当前执行块
  2. 当前执行块的微任务队列
  3. 宏任务队列


  1. Event 事件级别


  1. addEventListener 要主要保存 function 的引用,用于解绑


  1. 队列,先进先出(想起了梗,吃多了拉)


  1. 堆栈,先进后出(想起了梗,吃多了吐)


  1. 触发阶段 捕获>目标>冒泡


  1. Event 对象,针对不同的类型,有自己独特的属性。
相关文章
|
4月前
|
开发框架 前端开发 JavaScript
在微信框架模块中,基于Vue&Element前端的事件和内容的管理
在微信框架模块中,基于Vue&Element前端的事件和内容的管理
|
3月前
|
前端开发 JavaScript 开发者
掌握Web前端事件处理精髓:从事件冒泡到事件委托,轻松优化你的交互体验与代码性能!
【8月更文挑战第23天】在Web前端开发中,事件处理是实现用户交互的关键机制。其中,事件冒泡与事件委托是优化页面性能、简化代码的重要手段。事件冒泡是指事件从触发它的元素开始,沿着DOM树向上逐层传播至根节点的过程。通过阻止事件冒泡,可以控制事件的影响范围。而事件委托则是利用事件冒泡特性,在父元素上设置监听器来响应子元素的事件,这种方法减少了监听器的设置数量,特别适用于动态添加的子元素,提高了代码的可维护性和性能。掌握这两种技术,能帮助开发者构建更高效、更简洁的应用程序。
55 0
|
6月前
|
JSON JavaScript 前端开发
vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户
vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户
|
6月前
|
存储 安全 前端开发
PHP医院安全不良事件管理系统源码(AEMS)前端vue2+element+后端laravel8不良事件上报与闭环管理
医院不良事件上报与管理系统结合现代医院管理思路,遵照PDCA全面质量循环管理方法而设计,并在多家大型三甲医院成熟运用。系统从事件上报、基于人、机、料、法 、环的RCA分析、事件整改、效果评估实现了结构化、标准化、智能化的管理和分析,满足医院可追溯化、全流程闭环管理要求,满足等级医院评审细则要求,大力提高医院不良事件上报的效率,保障事件分析的准确性,促进医疗安全的提高,避免同类事件再次发生,改善整个医院医疗安全,从而实现医院安全医疗的目标。
79 3
|
6月前
|
JavaScript 前端开发 C++
【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
【5月更文挑战第2天】【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
|
6月前
|
前端开发 JavaScript
【Web 前端】什么是事件冒泡?什么是事件委托?
【4月更文挑战第22天】【Web 前端】什么是事件冒泡?什么是事件委托?
|
6月前
|
前端开发 JavaScript 数据安全/隐私保护
前端点击其他输入框的时候,对当上个输入框进行判断(鼠标移出输入框事件,和鼠标点击其他输入框触发事件)
前端点击其他输入框的时候,对当上个输入框进行判断(鼠标移出输入框事件,和鼠标点击其他输入框触发事件)
105 0
|
1月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
133 2
|
1月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
40 0
|
1月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。