🌟前言
哈喽小伙伴们,本文将收录在JavaScript【前端童子功】这个专栏里;这个专栏里边会收录一些JavaScript的基础知识和项目实战;希望大家可以多多支持,你们的支持就是我创作的动力;让我们一起来看看吧🤘
🌟事件
首先,什么是事件呢? 首先说JS就是为了实现一些动态的操作,而用户会有时候想去实现一些功能,如提交表单,鼠标点击等,就要在浏览器中触发这个事件,然后浏览器会感知(或者说捕获)到用户的这个行为,就会去响应处理这个事件。 这个就称之为 事件。
🌟绑定事件的方式:
🌟标签绑定事件:
<button onclick="click_fn()">click</button> <script> function click_fn(){ console.log(this); } </script>
🌟Document对象来绑定事件:on+事件type
注意:重复监听某一事件,后者会覆盖前者,而不会两者先后触发
<button>click</button> <script> var button1 = document.querySelector('button') button1.onclick=function(){ console.log("第一个点击事件的方法"); } var button2 = document.querySelector('button') button2.onclick=function(){ console.log("第二个点击事件的方法"); } //第二个点击事件的方法会覆盖第一个方法,所以点击只会触发第二次的点击事件方法 </script>
🌟 事件监听:使同一个对象的同一事件绑定多个事件处理程序。兼容IE9及以上。
为一个事件添加多个事件处理程序,解决了上面两种方法不能添加多个方法 更精细的控制事件监听器的触发阶段
🌟 绑定事件
语法:
element.addEventListener(事件名称(不写前缀),函数,布尔值(可不写));
参数 | 类型 | 描述 |
event | string | 表示事件类型的字符串 如:“click” “mouseover” 事件名称不添加on前缀 |
allback | function | 表示事件处理程序,函数中的this 指向添加监听的对象 |
bool | boolean | 可选,true表示在捕获阶段调用事件处理程序;false表示在冒泡阶段调用。后面会有事件流的详细解释 |
标签.addEventListener("事件名称",function(){},false); //兼容到IE9及其以上 标签.attachEvent("事件名称",function(){}) // ie8及以下
🌟 移除事件绑定
语法:
element.removeEventListener(event,callback,bool); <button id="myBtn"></button> <script type="text/javascript"> var btn=document.getElementById('myBtn'); function handle(){ console.log(this); } //兼容到IE9及其以上 btn.addEventListener('click',handle,false); //添加事件处理程序 btn.removeEventListener('click',handle,false); //移除事件处理程序 // ie8及以下 btn.attachEvent('onclick',handle); // 添加 btn.detachEvent('onclick',handle); // 移除 </script>
注意:当需要移除事件监听,不能使用匿名函数。必须能够获取函数引用。
🌟 事件监听的兼容写法
注/function addEvent(obj,type,handle){ try{ obj.addEventListener(type,handle,false); }catch(e){ try{ obj.attachEvent('on'+type,handle); } catch(e){ obj['on' + type]=handle; //早期浏览器 } } }
🌟事件对象
在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。所有浏览器都支持event对象,但支持方式不同。
🌟 应用场景:
- 需要知道你按下的键盘码时。
- 需要知道鼠标点击的坐标时。
- 阻阻止止冒泡流事件的发生。
🌟获取事件对象
event对象是事件程序的第一个参数(IE8及以下不支持)
<div id="box" style="height:30px;width:200px;background:pink;"></div> <script> var oBox = document.getElementById('box'); oBox.onclick = function(event){ box.innerHTML = event; } </script>
直接使用event变量(火狐浏览器不支持,输出event未定义)
<div id="box" style="height:30px;width:200px;background:pink;"></div> <script> var oBox = document.getElementById('box'); oBox.onclick = function(){ box.innerHTML = event; } </script>
兼容性写法
<div id="box" style="height:30px;width:200px;background:pink;"></div> <script> var oBox = document.getElementById('box'); oBox.onclick = function(e){ e = e || event; box.innerHTML = e; } oBox.addEventListener("click",function(e){},false) </script>
🌟 事件对象常用的方法和属性
🌟 鼠标事件相关
属性 | 含义 |
clientX | 当鼠标事件发生的时候,鼠标相对于浏览器X轴的位置 |
clientY | 当鼠标事件发生的时候,鼠标相对于浏览器Y轴的位置 |
offsetX | 当鼠标事件发生的时候,鼠标相对于事件源X轴的位置 |
offsetY | 当鼠标事件发生的时候,鼠标相对于事件源Y轴的位置 |
pageX | 当鼠标事件发生的时候,鼠标相对于浏览器X轴的位置,包含页面横向滚动距离 |
pageY | 当鼠标事件发生的时候,鼠标相对于浏览器X轴的位置,包含页面纵向滚动距离 |
🌟 滚轮事件相关:
属性 | 含义 |
wheelDelta | 获取滚轮的上下滚动。正值向上,负值向下。 |
e.wheelDelta 上: 120 240 下:-120 -240
🌟 键盘事件相关对象:
属性 | 含义 |
key | 获取当前所按键的名称 |
keyCode | 获取当前所按键的键盘码 |
ctrlKey | 判断当前ctrl键是否按下的状态 |
shiftKey | 判断当前shift键是否按下的状态 |
altKey | 判断当前alt键是否按下的状态 |
target | 获取当前元素的DOM对象 |
🌟 其他属性和方法
属性 | 含义 |
preventDefault() | 阻止浏览器默认行为 |
stopPropagation() | 阻止事件流的传播 [e.stopProagation();] |
currentTarget | 指向被绑定事件的元素 |
target | 指向事件触发的对象,当事件是处在冒泡或者捕获阶段调用的时候,指向最先触发事件的事件源 |
type | 返回当前所触发事件的事件名称 |
🌟事件流
事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。 事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事件流。
🌟 两种事件流模型
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。
on+type; 事件监听:false。
- 捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。
事件监听:ture。
IE9、Firefox、Chrome、Opera、和Safari都支持事件捕获。尽管DOM标准要求事件应该从document对象开始传播,但这些浏览器都是从window对象开始捕获事件的。
🌟 DOM事件流
DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。
🌟 DOM事件流的三个阶段
DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
eventPhase属性返回一个整数值,表示事件目前所处的事件流阶段:0表示事件没有发生,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段
- 事件捕获阶段:实际目标(
<div>
)在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到<html>
再到<body>
就停止了。 - 处于目标阶段:事件在
<div>
上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。 - 冒泡阶段:事件又传播回文档。
- 所有的事件都要经过捕获阶段和处于目标阶段,但是有些事件会跳过冒泡阶段:如,获得输入焦点的focus事件和失去输入焦点的blur事件。
🌟 事件委派
事件委派的原理用到的就是事件冒泡和目标元素,把事件处理器添加到父元素,等待子元素事件冒泡,并且父元素能够通过target(IE为srcElement)判断是哪个子元素,从而做相应处理。
🌟 用法
- 子元素的事件加到父元素上
- 触发事件时判断 触发该事件的元素是什么(e.target)
- 判断内容 innerHTML innerText
- 标签名 nodeName (判断的时候,标签名需要大写)
- 属性 e.target.hasAttribute(“属性名”); 有则是true 无则是false
- 类名 ID e.target.classList.contains(“类名”); 有则是true 无则是false
- 在判断成功中写对应的处理函数
🌟 应用场合
- 需要给大量元素添加同一事件处理程序的时候,提高代码运行的效率
- 在页面加载完成后新创建的元素, 比如通过ajax异步加载生成dom对象
🌟 自定义事件(观察者模式)
自定义事件,顾名思义,就是自己定义事件类型,自己定义事件处理函数.
🌟 事件创建
JS中,最简单的创建事件方法,是使用Event构造器:
var myEvent = new Event('event_name');
为了能够传递数据,使用 CustomEvent 构造器:
var myEvent = new CustomEvent('event_name', { detail:{ // 将需要传递的数据写在detail中,以便在EventListener中获取 // 数据将会在event.detail中得到 }, });
🌟 自定义事件的监听
JS的EventListener是根据事件的名称来进行监听的,我们进行自定义事件监听的时候,需要创建相应的监听器
//假设listener注册在window对象上 window.addEventListener('event_name', function(event){ // 如果是CustomEvent,传入的数据在event.detail中 console.log('得到数据为:', event.detail); // ...后续相关操作 });
进行到这一步,window对象上就有了event_name这个事件的监听器,当触发这个事件时,相应的回调函数就会触发
🌟 自定义事件的触发
普通的事件触发我们都有相对应的操作区,比如click,鼠标单击来触发,自定义事件需要我们显式的去触发它,使用dispatchEvent去触发(IE8低版本兼容,使用fireEvent);
if(window.dispatchEvent) { window.dispatchEvent(myEvent); } else { window.fireEvent(myEvent); }
🌟 简单的例子
var myEvent = new CustomEvent('event_name', { detail: { title: 'This is title!'}, }); window.addEventListener('event_name', function(event){ console.log('得到标题为:', event.detail.title); }); // 随后在对应的元素上触发该事件 if(window.dispatchEvent) { window.dispatchEvent(myEvent); } else { window.fireEvent(myEvent); }
🌟 DOM事件流的简单例子
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <style> #outer{ position: absolute; width: 400px; height: 400px; top:0; left: 0; bottom:0; right: 0; margin: auto; background-color: deeppink; } #middle{ position: absolute; width: 300px; height:300px; top:50%; left: 50%; margin-left: -150px; margin-top: -150px; background-color: deepskyblue; } #inner{ position: absolute; width: 100px; height:100px; top:50%; left:50%; margin-left: -50px; margin-top: -50px;; background-color: darkgreen; text-align: center; line-height: 100px; color:white; } #outer,#middle,#inner{ border-radius:100%; } </style> <body> <div id="outer"> <div id="middle"> <div id="inner"> click me! </div> </div> </div> <script> var innerCircle= document.getElementById("inner"); innerCircle.addEventListener("click", function () { alert("innerCircle的click事件在捕获阶段被触发"); },true); innerCircle.addEventListener("click", function () { alert("innerCircle的click事件在冒泡阶段被触发"); },false); var middleCircle= document.getElementById("middle"); middleCircle.addEventListener("click", function () { alert("middleCircle的click事件在捕获阶段被触发"); },true); middleCircle.addEventListener("click", function () { alert("middleCircle的click事件在冒泡阶段被触发"); },false); var outerCircle= document.getElementById("outer"); outerCircle.addEventListener("click", function () { alert("outerCircle的click事件在捕获阶段被触发"); },true); outerCircle.addEventListener("click", function () { alert("outerCircle的click事件在冒泡阶段被触发"); },false); </script> </body> </html>
🌟写在最后
更多JavaScript知识以及API请大家持续关注,尽请期待。各位小伙伴让我们 let’s be prepared at all times!