JS学习笔记(十三)事件

JS学习笔记(十三)事件

文章目录

  • JS学习笔记(十三)事件
  • 一、事件流
    • 1.1 事件冒泡
    • 1.2 事件捕获
    • 1.3 DOM 事件流
  • 二、事件处理程序(事件监听器)
    • 2.1 HTML 事件处理程序(不建议使用)
      • 2.1.1 HTML 事件处理程序的问题
    • 2.2 DOM0 事件处理程序
    • 2.3 DOM2 事件处理程序
      • 1. addEventListener()和 removeEventListener()
      • 2. attachEvent 注册事件
      • 3. 注册事件兼容性解决方案
    • 2.4 IE 事件处理程序
    • 2.5 跨浏览器事件处理程序
  • 三、事件对象
    • 3.1 DOM 事件对象
      • (1)target 和 currentTarget
        • e.target和this的区别
      • (2)type属性
      • (3)preventDefault()
      • (4)stopPropagation()
      • (5)eventPhase属性
    • 3.2 IE事件对象
      • (1)returnValue
      • (2)cancelBubble
  • 四、事件类型
    • 4.1 用户界面事件
      • (1)load
        • 1. 指定load事件的方法
        • 2. 会触发load事件的情况
      • (2)unload 事件
    • 4.2 焦点事件
    • 4.3 鼠标和滚轮事件
      • 1. 客户端坐标
      • 2. 页面坐标
      • 3. 屏幕坐标
      • 4. 修饰键
      • 5. 相关元素
      • 6. 鼠标按键
      • 7. 额外事件信息
      • 8. 触摸屏设备
      • 9. 禁止鼠标选中文字
      • 10. mouseenter 和 mouseover 的区别(经典面试题)
    • 4.4 键盘与输入事件
      • 键盘事件
      • 1. 键码
      • 2. 字符编码
      • 3. DOM3 的变化
      • 4. textInput事件
        • event.data
        • event.inputMethod
    • 4.5 合成事件
    • 4.6 HTML5事件
      • 1. contentmenu事件
      • 2. beforeunload事件
      • 3.DOMContentLoaded事件
      • 4. readystatechange事件
      • 5. pageshow 和 pagehide事件
        • (1)pageshow
        • (2)pagehide
      • 6. haschange事件
    • 4.7 设备事件
      • 1. orientationchange 事件
      • 2. deviceorientation事件
      • 3. devicemotion 事件
    • 4.8 触摸及手势事件
      • 1. 触摸事件
      • 2. 手势事件
  • 五、内存与性能
    • 5.1 事件委托(重点)
    • 5.2 删除事件处理程序
  • 六、模拟事件
    • 6.1 DOM 事件模拟
      • 1. 模拟鼠标事件
      • 2. 模拟键盘事件
      • 3. 模拟其他事件
      • 4. 自定义DOM事件
    • 6.2 IE事件模拟

       JS和HTML的交互是通过事件实现的,可以使用仅在事件发生时执行的监听器(处理程序)订阅事件。在传统软件工程领域,这个模型叫”观察者模式“,其能够做到也页面行为与页面展示的分离。

事件三要素:

  • 事件源:事件被触发的对象
  • 事件类型:如何触发什么事件(如:鼠标经过触发还是键盘按下触发)
  • 事件处理程序:通过一个函数赋值的方法完成

 

一、事件流

事件流描述了页面接收事件的顺序

DOCTYPE html>
<html lang="en">
    <head>
        <title>Documenttitle>
    head>
    <body>
        <div id="myDiv">Click Mediv>
    body>
html>

 

1.1 事件冒泡

       IE 事件流称为事件冒泡,因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)

点击上面的civ后,click事件发生的顺序:

JS学习笔记(十三)事件_第1张图片

       

1.2 事件捕获

       最不具体的节点最先收到事件,而最具体的节点最后收到事件。事件捕获实际上是为了在事件到达最终目的前拦截事件。

       点击上面的civ后,click事件发生的顺序:

JS学习笔记(十三)事件_第2张图片

       

1.3 DOM 事件流

       DOM2 Event 规定事件流分为3个阶段:事件捕获、到达目标、事件冒泡

JS学习笔记(十三)事件_第3张图片

       

二、事件处理程序(事件监听器)

事件处理程序的名字以on开头
       

2.1 HTML 事件处理程序(不建议使用)

       特定元素支持的每个事件都可以使用事件处理程序得到名字以HTML属性的形式来指定。

       注意: 因为属性的值是JS代码,所以不能在未转义的情况下使用HTML语句,如符号和好(&)、双引号、大小于号。为避免使用HTML实体,可以使用单引号代替双引号

<script>
    function showMessage() {
       
        console.log("Hello World!");
    }
script>
<input type="button" value="Click me" onclick="showMessage()">

       以调用函数指定的事件处理函数首先会创建一个函数来封装属性的值。该函数有个特殊的局部变量event,其中保存的是event对象。动态创建的包装函数其作用域链被扩展了。document和元素自身的成员都可以被当成局部变量来访问。通过with实现,意味着事件处理程序可以更方便的访问自己的属性

function() {
     
    with(document) {
     
        with(this) {
     
            // 属性值
        }
    }
}

       

2.1.1 HTML 事件处理程序的问题

  1. 时机问题

    有可能HTML元素已经显示在页面上,用户已经与其交互,而事件处理程序得代码还无法执行

  2. 对事件处理程序作用域链的扩展在不同浏览器中可能导致不同的结果

  3. HTML 和 JS 强耦合

       

2.2 DOM0 事件处理程序

       JS中指定事件处理程序得传统方法是:把一个函数赋值给(DOM元素)一个事件处理程序属性。 因为该方法简单,现在所有浏览器仍然支持此方法。

       要使用JS指定事件处理程序,必须先获得操作对象得引用。然后将事件处理程序属性赋值为一个函数

let btn = document.getElementById("myBtn");
btn.onclick = function() {
     
	console.log(this.id);
}

       事件处理程序会在元素的作用域里运行,即this等于元素。在事件处理程序里通过this可以访问元素的任何属性和方法。以这种方法添加事件处理程序是注册在事件流的冒泡阶段

       通过将事件处理程序属性设置为null,可以移除通过DOM0方式添加的事件处理程序。

       

2.3 DOM2 事件处理程序

1. addEventListener()和 removeEventListener()

       DOM2 为事件处理程序的赋值和移除添加了两个方法:addEventListener()和 removeEventListener()。接收3个参数:事件名、事件处理函数和一个布尔值。true表示在捕获阶段调用事件处理程序。false表示在冒泡阶段调用事件处理程序。

let btn = document.getElementById("myBtn");
btn.addEventListener("click",() => {
     
  console.log(this.id);
},false);

也可以把方法抽象出去

let btn = document.getElementById("myBtn");
let handler = function() {
     
    console.log(this.id);
}
btn.addEventListener("click",handler,false);

注意:

  1. 里面的事件类型必须写成字符串类型,一定要加引号,且不带on
  2. 同一个元素,同一个事件可以添加多个监听器

 

2. attachEvent 注册事件

ie9 以前支持

注意:

  • 里面的事件类型要带on,如:onclick

 

3. 注册事件兼容性解决方案

function addEventListener(element,eventName,fn) {
     
  if(element.addEventListener) {
     
    element.addEventListener(eventName,fn); //第三个参数默认false
  } else if(element.attachEvent) {
     
    element.attachEvent('on'+eventName,fn);
  } else {
     
    //相当于element.onclick = fn;
    element['on'+ eventName] = fn;
  }
}

       

2.4 IE 事件处理程序

       IE 实现了和DOM类似的方法,即attachEvent() 和 detachEvent()。这两个方法接收两个同样的参数:事件处理程序的名字和事件处理函数,使用attachEvent()添加的事件会添加到冒泡阶段

let btn = document.getElementById("myBtn");
btn.attachEvent("onclick",() => {
     
  console.log("clicked"));
});

注意:

  • attachEvent()的第一个参数是以on开头的事件名
  • 在IE中使用attachEvent()与使用DOM0的主要区别是事件处理程序的作用域。使用DOM0时,事件处理程序中的this等于目标元素。使用attachEvent()时,事件处理程序是在全局作用域进行的,即this等于windows
  • attachEvent()也可以添加多个事件处理程序,但事件处理程序会以添加他们的顺序反向触发。

       

2.5 跨浏览器事件处理程序

       为确保事件处理程序具有最大的兼容性,需要让代码在冒泡阶段运行

       为实现跨浏览器事件处理程序,需要创建 addHandler()。该方法根据需要分别使用DOM0、DOM2或IE方法添加事件处理程序。该方法会在**EventUtil()**对象上添加一个方法,以实现跨浏览器事件处理。添加的addHandler()接收3个参数:目标元素、事件名和事件处理程序

let btn = document.getElementById("myBtn");
let handler = function() {
     
  console.log("clicked");
}
EventUtil.addHandler(btn,"click",handler);

       addHandler() 和 removeHandler() 并没有解决所有跨浏览器一致性问题,比如IE的作用域问题、多个事件处理程序执行顺序问题

       

三、事件对象

       在DOM中发生事件时,所有相关信息都会被收集并存储在一个名为event的对象中,这个对象包括一些基本信息:如导致时间的元素,发生的事件类型以及可能与特定事件相关的任何其他数据
       

3.1 DOM 事件对象

       在DOM合规的浏览器中,event对象是传给事件处理程序的唯一参数。不管以哪种方法(DOM0 和 DOM2)指定事件处理程序,都会传入这个event对象

       事件包含的公共属性和方法:

JS学习笔记(十三)事件_第4张图片 JS学习笔记(十三)事件_第5张图片

 

(1)target 和 currentTarget

       在事件处理程序内部,this 对象始终等于 currentTarget 的值,而target只包含事件的实际目标。如果事件处理程序直接添加在了意图的目标,则this、currentTarget 和 target的值是一样的。

       若事件处理程序是添加到按钮的父节点上,那他们的值就不一样

let btn = document.getElementById("myBtn");
document.body.onclick = function(event) {
     
  console.log(event.currentTarget === document.body);//true
  console.log(this === document.body);//true
  console.log(event.target === document.getElementById("myBtn")); //true
}

 

e.target和this的区别

区别:

  • e.target :点击了哪个元素就返回哪个元素
  • this :哪个元素绑定了事件,就返回哪个元素

 

(2)type属性

应用场景:处理程序处理多个事件

(3)preventDefault()

用于阻止特定事件的默认动作。比如链接的默认行为

(4)stopPropagation()

用于立即阻止事件流在DOM结构中传播,取消后续事件的捕获或冒泡。

(5)eventPhase属性

用于确认事件流当前所处的阶段。

       

3.2 IE事件对象

       与DOM 事件不同,IE事件可以基于事件处理程序被指定的方式以不同的方法来访问。如果事件处理程序是使用DOM0方式指定的,则event对象只是window对象的一个属性。若事件处理程序是使用attachEvent()指定的,则event对象会作为唯一的参数传给处理函数,event对象仍然是window对象的属性。

       IE事件对象包含的公共属性和方法:

JS学习笔记(十三)事件_第6张图片

 
       事件处理程序的作用域取决于指定它的方式,因此this值并不总等于事件目标。因此,更好的是用事件对象的srcElement属性代替this

(1)returnValue

       等价于DOM的preventDefault(),用于取消给定事件默认的行为。returnValue = false;即设置阻止默认动作

(2)cancelBubble

       与DOM的stopPropogation()一样,都可以阻止事件冒泡,stopPropagation()即可取消捕获也取消冒泡

       

四、事件类型

DOM3 Event定义如下事件类型:

  • 用户界面事件(UIEvent)
  • 焦点事件(FocusEvent)
  • 鼠标事件(MouseEvent)
  • 滚轮事件(WheelEvent):使用鼠标滚轮是触发
  • 输入事件(InputEvent)
  • 键盘事件(KeyBoardEvent)
  • 合成事件(CompositionEvent):使用某种IME(输入法编辑器)输入字符时触发

       

4.1 用户界面事件

事件有:

  • DOMActive:元素被激活时触发,DOM3中被废除
  • load:在window上当页面加载完成后触发,在窗套()上当所有窗格()都加载完成后触发,在元素上当图片加载完成后触发,在元素上当相应对象加载完成后触发。
  • unload:在window上当页面完全卸载后触发,在窗套上当所有窗格都卸载完成后触发,在元素上当相应对象无法加载时触发。
  • abort:在元素上当相应对象加载完成前被用户提前终止下载时触发
  • error
  • select:在文本框(input或textarea)上当用户选择了一个或多个字符时触发
  • resize:在window或窗格上当窗口或窗格被缩放时触发
  • srcoll
  • (1)load

    1. 指定load事件的方法

           最常用的事件。load事件会在整个页面(包括所有外部资源)加载完后触发。有两种方式指定load事件:

    • JS方式(推荐使用)
    window.addEventListener("load",(event)=>{
         
    	...
    })
    
    • 元素添加onload属性
    DOCTYPE html>
    <html lang="en">
    <head>
      <title>Documenttitle>
    head>
    <body onload="console.log('hhh')">
    body>
    html>
    

           

    2. 会触发load事件的情况

    • 图片也会触发load事件,包括DOM中的图片和非DOM中的图片

    给元素指定一个在加载完成后执行的事件处理程序:

    window.addEventListener("load",() => {
         
      let image = document.createElement("img");
      image.addEventListener("load", (event) => {
         
        console.log(event.target.src);
      });
      document.body.appendChild(image);
      image.src = "smile.gif";
    })
    

    注意:下载图片并不一定要把元素添加到文档,只要给他设置src属性就会立即开始下载

    • 你可能感兴趣的:(JavaScript,html5,html,javascript)