百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

总结JavaScript事件机制

zhezhongyun 2024-12-09 19:02 58 浏览

JavaScript事件模型

在各种浏览器中存在三种事件模型: 原始事件模型 , DOM2事件模型 , IE事件模型。

其中原始的事件模型被所有浏览器所支持,而DOM2中所定义的事件模型目前被除了IE以外的所有主流浏览器支持.

原始事件模型:

在原始事件模型中(也有说DOM0级),事件发生后没有传播的概念,没有事件流。事件发生,处理,结束,就这么简单。监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。书写方式有两种:

(1) HTML代码中指定属性值:<input type=”button” onclick=”func” />

(2) 在js代码中指定属性值:document.getElementsByTagName(‘input’)[0].onclick = func

优点:所有浏览器都兼容

缺点:

1.逻辑与显示没有分离

2.相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的

3.无法通过事件的冒泡、委托等机制。

DOM2事件模型

此模型是W3C制定的标准模型。W3C制定的事件模型中,一次事件的发生包含三个过程:

(1)事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。

(2)事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数.

(3)事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行。

所有的事件类型都会经历 "事件捕获阶段" 但是只有部分事件会经历 "事件冒泡阶段" 阶段,例如submit事件就不会被冒泡。

e.target与e.currentTarget是干什么的?

e.target获取当前实际触发事件节点,e.currentTarget获取获取当前监听节点。

<div>
     <span>11111</span>
</div>

$('div').on('click', function(e){
console.log(e.currentTarget);
console.log(e.target);
})

如果点击span的输出:

li对象

span对象

点击li的非span区域,输出

preventDefault与stopPropagation是干什么的

preventDefault取消事件默认动作,如下例,页面不会跳转

<a href='baidu.com' onclick="stop(e)">

//js:
function stop(e){
  e.preventDefault;
}

stopPropagation阻止元素冒泡,下例 点击child div,parent 的 alert 不会执行

<div id="parent" onclick="alert(this.id)" >

     <div id="child" onclick="doSomething;" ></div>

</div>

//js
function doSomething(e){
    e.stopPropagation
}

什么是dispatchEvent?

dispatchEvent是js的事件触发器,事件触发器就是用来触发某个元素下的某个事件。

可以自定义事件,通过触发器触发。

document.addEventListener('test', function(e){
    console.log(e.msg)
});
var e = document.createEvent('HTMLEvents');
e.initEvent('test', true, true);
e.msg = ' test dispatchEvent';
document.dispatchEvent(e);

//最终输出 test dispatchEvent

如何实现事件代理,封装一个方法:

首先介绍一下JavaScript的事件代理。事件代理在JS世界中一个非常有用也很有趣的功能。

当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数,

这主要得益于浏览器的事件冒泡机制。

以下封装一个简单的实现,只支持id绑定和节点选择

<ul id="list">
	<li>1</li>
	<li>2</li>
	<li>3</li>
	<div>div</div>
</ul>

<script>
function delegation(id, node, event, cb) {
	var el = document.getElementById(id);
	el.addEventListener(event, function(e){
		if(e.target.nodeName.toLocaleLowerCase == node.toLocaleLowerCase){
			cb && cb(e);
		}
	})
}

delegation('list', 'li', 'click', function(e){
    console.log(e.target.textContent);
})
</script>

事件代理的问题:

<li><span></span></li>如果同时给span与li绑定事件该如何阻止冒泡???

代码如下:事件代理同时绑定了li和span,当点击span的时候,li和span都会冒泡。

<li>
    <span></span>
</li>


$(document).on('click', 'li', function{
  alert('li click');
});

$(document).on('click', 'span', function{
  alert('li span');
})

获取当前事件的target目标元素,如果是span标签,就不执行li标签绑定事件的逻辑。

$(document).on('click', 'li', function(e){
  if(e.target.nodeName == 'SPAN') {
      e.stopPropagation;
      return;  
  }
  alert('li click');
});

tap事件是如何实现的

以下是zepto部分源码,tap是一个自定义事件,监听touchend,并且250ms之内没有触摸操作而被触发

 .on('touchend MSPointerUp pointerup', function(e){
       
 tapTimeout = setTimeout(function {

 // trigger universal 'tap' with the option to cancelTouch
 // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
 var event = $.Event('tap')
 event.cancelTouch = cancelAll
 // [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap
 if (touch.el) touch.el.trigger(event)

 // trigger double tap immediately
 if (touch.isDoubleTap) {
 if (touch.el) touch.el.trigger('doubleTap')
 touch = {}
 }

 // trigger single tap after 250ms of inactivity
 else {
 touchTimeout = setTimeout(function{
 touchTimeout = null
 if (touch.el) touch.el.trigger('singleTap')
 touch = {}
 }, 250)
 }
 }, 0)
 } else {
 touch = {}
 }
 deltaX = deltaY = 0

      })

tap会产生什么问题

tap会出现目前所谓“点透”的情况,下图是的黑色透明遮罩绑定了tap,提交按钮绑定了click事件,如果在按钮的位置点击遮罩,会同时触发click和tap,

tap的延迟为250毫秒,而click事件的延迟是300毫秒。tap触发隐藏遮罩后,click刚好延迟结束,此时按钮就会被点击。

zepto的touch库做了什么

zepto touch库通过touchmove,touchstart和touchend,封装了自定义事件:触摸,双击,长按,滑动,方向滑动等。

fastclick解决了什么问题

fastclick解决了click事件延迟的问题,因为300毫秒的延迟会造成很多问题,在移动端会干扰touch事件。

fastclick核心代码:

FastClick.prototype.onTouchEnd = function(event){
  if (!this.needsClick(targetElement)) {
    // 则屏蔽原生事件,避免触发两次click
    event.preventDefault; 
    // 触发一次模拟的click
    this.sendClick(targetElement, event);
  }
}
FastClick.prototype.sendClick = function(targetElement, event) {

  // 创建一个鼠标事件
  clickEvent = document.createEvent('MouseEvents');
  // 初始化鼠标事件为click事件
  clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);

  // fastclick的内部变量,用来识别click事件是原生还是模拟
  clickEvent.forwardedTouchEvent = true;

  // 在目标元素上触发该鼠标事件,
  targetElement.dispatchEvent(clickEvent);

相关推荐

EU Said to Accept a 10% U.S. Universal Tariff while Seeking Exemptions for Key Sectors

TMTPOST--TheEuropeanUnionmaymakeconcessionstosecureexemptionsfromtariffsonkeysectors...

抖音品质建设 - iOS启动优化《实战篇》

前言启动是App给用户的第一印象,启动越慢,用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环。启动优化涉及到的知识点非常多,面也很广,一篇文章难以包含全部,所以拆分成两部分:原理和实战...

荷兰引进美国诗人阿曼达·戈尔曼诗作,因译者肤色遭抵制

记者|刘亚光阿曼达在拜登就职典礼上朗诵诗歌。图源:PatrickSemansky/AssociatedPress阿曼达·戈尔曼(AmandaGorman)出生于1998年,自小患有语言障碍,...

EU and U.S. Upbeat on Trade Deal Ahead of July Deadline

TMTPOST--TheEuropeanUnionandtheUnitedStatesseemupbeatontheirtradeagreementtoavoidtr...

“过期食品”英文怎么说?(过期食品)

在购买食品时,我们都会特别留意一下食物的保质期有多久,是否新鲜,以免买到过期的商品。TheafternoonteaspreadatThePeninsulaBoutiqueandCaf...

世界首富撩妹露骨短信遭曝光 网友评论亮了

原标题:世界首富如何撩妹?亚马逊创始人贝索斯给情妇的露骨短信曝光这周最大的一个瓜,可能就是亚马逊首席执行官杰夫·贝佐斯(JeffBezos)与妻子麦肯齐(MacKenzie)离婚的惊人消息。紧接...

征收熊孩子“尖叫费”不合理?店主回怼网友

爱尔兰一家很受欢迎的咖啡馆要收“孩童尖叫费”,网友们。。。爱尔兰一咖啡店店主5月4日在脸书发帖,表示要向带有吵闹孩童的顾客多收15%的额外费用,引发了大批网友的议论。原贴内容如下:图viaFaceb...

Rationality, objectivity and pragmatism win the day in Geneva to benefit of all

ApressbriefingisheldbytheChinesesidefollowingtheChina-UShigh-levelmeetingoneconomica...

Dify「模板转换」节点终极指南:动态文本生成进阶技巧(附代码)Jinja2引擎解析|6大应用场景实战

这篇文章是关于Dify「模板转换」节点的终极指南,解析了基于Jinja2模板引擎的动态文本生成技巧,涵盖多源文本整合、知识检索结构化、动态API构建及个性化内容生成等六大应用场景,助力开发者高效利用模...

微软 Edge 浏览器 96.0.4664.93 稳定版发布:修复大量安全问题

IT之家12月12日消息,据外媒mspoweruser消息,微软12月11日为Edge浏览器推出了96.0.4664.93稳定版。该版本没有增加新功能,而是修复了大量漏洞,...

HarmonyOS NEXT仓颉开发语言实战案例:健身App

各位好,今日分享一个健身app的首页:这个页面看起比之前的案例要稍微复杂一些,主要在于顶部部分,有重叠的背景,还有偏移的部分。重叠布局可以使用Stack容器实现,超出容器范围的偏移可以使用负数间距来实...

如果使用vue3.0实现一个modal,你会怎么设计?

这是个很好的问题!设计一个Vue3.0Modal时,我建议按照可复用、高扩展、简洁的原则来实现。下面我给你一个清晰的设计思路,涵盖组件拆分、使用方式以及Vue3中特性(如Telepor...

在进行APP切图的前,我们需要做什么?

切图是个技术活,小伙伴们千万不能忽视切图的重要性噢,前文介绍了设计的七大元素,那么我们现在来看看在切图之前,我们需要做什么呢?。1、和客户端的技术沟通好用不同的框架来实现的时候,图会有不一样的切法。...

独立开发问题记录-margin塌陷(独立提出历史问题)

一、概述往事如风,一周就过去了。上周在Figma里指点江山,这周在前端代码里卑微搬砖。回想上周,在Figma中排列组合,并且精确到1像素。每设计出一个页面,成就感就蹭蹭往上涨。没想到还没沾沾自喜多久,...

循序渐进Vue+Element 前端应用开发(8)—树列表组件的使用

在我前面随笔《循序渐进VUE+Element前端应用开发(6)---常规Element界面组件的使用》里面曾经介绍过一些常规的界面组件的处理,主要介绍到单文本输入框、多文本框、下拉列表,以及按钮...