JS高级程序设计——第13章事件 13.4 事件类型(键盘与文本事件、复合事件、变动事件)

一、键盘事件

  1. 用户在使用键盘时会触发键盘事件。“DOM2 级事件”最初规定了键盘事件,但在最终定稿之前又 删除了相应的内容。结果,对键盘事件的支持主要遵循的是 DOM0 级

  2. “DOM3 级事件”为键盘事件制定了规范IE9 率先完全实现了该规范。其他浏览器也在着手实现这 一标准,但仍然有很多遗留的问题。

  3. 3 个键盘事件,简述如下。keydownkeypresskeyup
    在这里插入图片描述

  4. 虽然所有元素都支持以上 3 个事件,但只有在用户通过文本框输入文本时才最常用到。

  5. 在用户按了一下键盘上的字符键时,首先会触发 keydown 事件,然后紧跟着是 keypress 事件, 最后会触发 keyup 事件

  • 其中,keydown 和 keypress 都是在文本框发生变化之前被触发的;而 keyup 事件则是在文本框已经发生变化之后被触发的
  • 如果用户按下了一个字符键不放,就会重复触发 keydown 和 keypress 事件,直到用户松开该键为止。
  • 如果用户按下的是一个非字符键,那么首先会触发 keydown 事件,然后就是 keyup 事件。如果按 住这个非字符键不放,那么就会一直重复触发 keydown 事件,直到用户松开这个键,此时会触发 keyup 事件

二、文本事件

  1. 只有一个文本事件:textInput。这个事件是对 keypress 的补充,用意是在将文本显示给用户之前更容易拦截文本。在文本插入文本框之前会触发 textInput 事件
  • 根据规范,当用户在可编辑区域中输入字符时,就会触发这个事件。
  1. keypress 和 textInput 事件的区别:
  • 区别之一就是任何可以获得焦点的元素都可以触发 keypress 事件但只有可编辑区域才能触发 textInput 事件
  • 区别之二是 textInput 事件只会在用户按下能够输入实际字符的键时才会被触发,而 keypress 事件则在按下那些能够影响文本显示的键时也会触发(例如退格键)。
  1. textInput 事件的data 属性:由于 textInput 事件主要考虑的是字符,因此它的 event 对象中还包含一个 data 属性,这个属性的值就是用户输入的字符(而非字符编码)。换句话说,用户在没有按上档键的情况下按下了 S 键, data 的值就是"s",而如果在按住上档键时按下该键,data 的值就是"S"。【关注的是实际输入的是什么】
  2. 以下是一个使用 textInput 事件的例子:
    在这里插入图片描述

三、键码

1、keyCode 属性
  1. 在发生 keydown 和 keyup 事件时,event 对象的 keyCode 属性中会包含一个代码,与键盘上一个特定的键对应
  • 数字字母字符键,keyCode 属性的值与 ASCII 码中对应小写字母或数字的编码相同。因此,数字键 7 的 keyCode 值为 55,而字母 A 键的 keyCode 值为 65——与 Shift 键的状态无关DOM 和 IE 的 event 对象都支持 keyCode 属性。请看下面这个例子:
    在这里插入图片描述
  • 下表列出 了所有非字符键的键码。
    在这里插入图片描述
    在这里插入图片描述
    无论 keydown 或 keyup 事件都会存在的一些特殊情况在 Firefox 和 Opera 中,按分号键时 keyCode 值为 59,也就是 ASCII 中分号的编码;但 IE 和 Safari 返回 186,即键盘中按键的键码

三、字符编码

发生 keypress 事件意味着按下的键会影响到屏幕中文本的显示在所有浏览器中,按下能够插入 或删除字符的键都会触发 keypress 事件;按下其他键能否触发此事件因浏览器而异

由于截止到 2008 年,尚无浏览器实现“DOM3 级事件”规范,所以浏览器之间的键盘事件并没有多大的差异

1、 charCode 属性
  1. charCode 属性:IE9、Firefox、Chrome 和 Safari 的 event 对象都支持一个 charCode 属性,这个属性只有在发生 keypress 事件时才包含值,而且这个值是按下的那个键所代表字符的 ASCII 编码。此时的 keyCode 通常等于 0 或者也可能等于所按键的键码
  • IE8 及之前版本和 Opera 则是在 keyCode 中保存字符的 ASCII 编码。要想以跨浏览器的方式取得字符编码,必须首先检测 charCode 属性是否可用,如果不可用则使 用 keyCode,如下面的例子所示。
    在这里插入图片描述
  • 下面是使用这个方法的示例。
 var textbox = document.getElementById("myText");
    EventUtil.addHandler(textbox, "keypress", function(event){
        event = EventUtil.getEvent(event);
        alert(EventUtil.getCharCode(event));
});

在取得了字符编码之后,就可以使用 String.fromCharCode()将其转换成实际的字符

四、DOM3 级变化

1、新增key、keyIdentifier 或 char属性(跨浏览器开发时不推荐使用)
  1. 尽管所有浏览器都实现了某种形式的键盘事件,DOM3 级事件还是做出了一些改变。
  • 比如,DOM3级事件中的键盘事件,不再包含 charCode 属性,而是包含两个新属性:key 和 char

  • 其中,key 属性是为了取代 keyCode 而新增的,它的值是一个字符串

    在按下某个字符键时,key的值就是相应的文本字符(如“k”或“M”);
    在按下非字符键时, key 的值是相应键的名(如“Shift” 或“Down”)。

  • char 属性在按下字符键时的行为与 key 相同,但在按下非字符键时值为 null

  • IE9 支持 key 属性,但不支持 char 属性

    Safari 5 和 Chrome 支持名为 keyIdentifier 的属性, 在按下非字符键(例如 Shift)的情况下与 key 的值相同。对于字符键keyIdentifier 返回一个格式类似“U+0000”的字符串,表示 Unicode 值。

var textbox = document.getElementById("myText");
    EventUtil.addHandler(textbox, "keypress", function(event){
        event = EventUtil.getEvent(event);
        var identifier = event.key || event.keyIdentifier;
        if (identifier){
         alert(identifier);
    }
});

由于存在跨浏览器问题,因此本书不推荐使用 key、keyIdentifier 或 char

2、添加了location 的属性(不推荐使用)
  1. location 的属性: DOM3 级事件还添加了一个名为 location 的属性这是一个数值,表示按下了什么位置上的键: 0 表示默认键盘,1 表示左侧位置(例如左位的 Alt 键),2 表示右侧位置(例如右侧的 Shift 键),3 表示 数字小键盘,4 表示移动设备键盘(也就是虚拟键盘),5 表示手柄(如任天堂 Wii 控制器)
  • IE9 支持这 个属性。Safari 和 Chrome 支持名为 keyLocation等价属性但即有 bug——值始终是 0,除非按下了数字键盘(此时,值 为 3);否则,不会是 1、2、4、5
    在这里插入图片描述
    与 key 属性一样,支持 location 的浏览器也不多,所以在跨浏览器开发中不推荐使用
3、getModifierState()方法(不推荐使用)

最后是给 event 对象添加了 getModifierState()方法。这个方法接收一个参数,即等于 Shift、 Control、AltGraph 或 Meta 的字符串,表示要检测的修改键。如果指定的修改键是活动的(也就是 处于被按下的状态),这个方法返回 true,否则返回 false。
在这里插入图片描述
实际上,通过 event 对象的 shiftKey、altKey、ctrlKey 和 metaKey 属性已经可以取得类似的属性了IE9 是唯一支持 getModifierState()方法的浏览器。

六、设备中的键盘事件

任天堂 Wii 会在用户按下 Wii 遥控器上的按键时触发键盘事件。尽管没有办法访问 Wii 遥控器中的所有按键,但还是有一些键可以触发键盘事件。遥控器上的一些键有对应的键码,通过这些键码可以知道用户按下了哪个键

iOS 版 Safari 和 Android 版 WebKit 在使用屏幕键盘时会触发键盘事件

七、复合事件(用处不大)

  1. 复合事件(composition event)是 DOM3 级事件中新添加的一类事件**,用于处理 IME 的输入序列**。
  2. IME(Input Method Editor,输入法编辑器)可以让用户输入在物理键盘上找不到的字符。例如,使用拉 丁文键盘的用户通过 IME 照样能输入日文字符。IME 通常需要同时按住多个键,但最终只输入一个字符。复合事件就是针对检测和处理这种输入而设计的
  3. 有以下三种复合事件。
    在这里插入图片描述
    在这里插入图片描述
  4. 复合事件与文本事件在很多方面都很相似。在触发复合事件时,目标是接收文本的输入字段。但它比文本事件的事件对象多一个属性 data,其中包含以下几个值中的一个:
    在这里插入图片描述
  5. 与文本事件一样,必要时可以利用复合事件来筛选输入。可以像下面这样使用它们:
    在这里插入图片描述
    IE9+是到 2011 年唯一支持复合事件的浏览器。由于缺少支持,对于需要开发跨浏览器应用的开发 人员,它的用处不大。要确定浏览器是否支持复合事件,可以使用以下代码:
    在这里插入图片描述

八、变动事件

1、变动事件种类
  1. DOM2 级的变动(mutation)事件在 DOM 中的某一部分发生变化时给出提示变动事件是为 XML 或 HTML DOM 设计的,并不特定于某种语言。DOM2 级定义了如下变动事件。
    在这里插入图片描述

  2. 使用下列代码可以检测出浏览器是否支持变动事件:

    var isSupported = document.implementation.hasFeature("MutationEvents", "2.0");
    

    IE8 及更早版本不支持任何变动事件。下表列出了不同浏览器对不同变动事件的支持情况。
    在这里插入图片描述
    由于 DOM3 级事件模块作废了很多变动事件,所以本节只介绍那些将来仍然会得到支持的事件。

2、删除节点

1.DOMNodeRemoved事件:在使用 removeChild()或 replaceChild()从 DOM 中删除节点时,首先会触发 DOMNodeRemoved事件。这个事件的目标(event.target)是被删除的节点,而 event.relatedNode 属性中包含着对目标节点父节点的引用

这个事件触发时,节点尚未从其父节点删除,因此其 parentNode 属性仍然 指向父节点(与 event.relatedNode 相同)。这个事件会冒泡,因而可以在 DOM 的任何层次上面处理它

  1. DOMNodeRemovedFromDocument 事件:如果被移除的节点包含子节点,那么在其所有子节点以及这个被移除的节点上会相继触发 DOMNodeRemovedFromDocument 事件【因为这些子节点也被移除了文档】。

但这个事件不会冒泡,所以只有直接指定给其中一个子节点的 事件处理程序才会被调用。这个事件的目标是相应的子节点或者那个被移除的节点,除此之外 event 对象中不包含其他信息。

  1. DOMSubtreeModified 事件紧随其后触发的是 DOMSubtreeModified 事件。这个事件的目标是被移除节点的父节点;此时的 event 对象也不会提供与事件相关的其他信息。
  2. 为了理解上述事件的触发过程,下面我们就以一个简单的 HTML 页面为例。
    在这里插入图片描述
    在这个例子中,我们假设要移除<ul>元素。此时,就会依次触发以下事件。
    (1) 在<ul>元素上触发 DOMNodeRemoved 事件。relatedNode 属性等于 document.body。
    (2) 在<ul>元素上触发 DOMNodeRemovedFromDocument 事件。
    (3) 在身为<ul>元素子节点的每个<li>元素及文本节点上触发DOMNodeRemovedFromDocument事件。
    (4) 在 document.body 上触发 DOMSubtreeModified 事件,因为<ul>元素是 document.body的直接子元素。
  • 运行下列代码可以验证以上事件发生的顺序:
    在这里插入图片描述
    以上代码为 document 添加了针对 DOMSubtreeModified 和 DOMNodeRemoved 事件的处理程序, 以便在页面上处理这些事件。由于DOMNodeRemovedFromDocument 不会冒泡,所以我们将针对它的事件处理程序直接添加给了<ul>元素的第一个子节点(在兼容 DOM 的浏览器中是一个文本节点)。在 置了以上事件处理程序后,代码从文档中移除了<ul>元素。
3、插入节点
  1. 在使用 appendChild()、replaceChild()或 insertBefore()向 DOM 中插入节点时,首先会触发 DOMNodeInserted 事件。这个事件的目标是被插入的节点,而 event.relatedNode 属性中包含 一个对父节点的引用。在这个事件触发时,节点已经被插入到了新的父节点中。这个事件是冒泡的,因此可以在 DOM 的各个层次上处理它。
  2. 紧接着,会在新插入的节点上面触发 DOMNodeInsertedIntoDocument 事件。这个事件不冒泡, 因此必须在插入节点之前为它添加这个事件处理程序。这个事件的目标是被插入的节点,除此之外 event 对象中不包含其他信息。
  3. 最后一个触发的事件是 DOMSubtreeModified,触发于新插入节点的父节点
  4. 我们仍以前面的 HTML 文档为例,可以通过下列 JavaScript 代码来验证上述事件的触发顺序。
EventUtil.addHandler(window, "load", function(event){ 
	var list = document.getElementById("myList");
	var item = document.createElement("li"); 			   
	item.appendChild(document.createTextNode("Item 4"));
	EventUtil.addHandler(document, "DOMSubtreeModified", function(event){  
		alert(event.type);
		alert(event.target);
	});
	EventUtil.addHandler(document, "DOMNodeInserted", function(event){
	    alert(event.type);
	    alert(event.target);
	    alert(event.relatedNode);
	});
	EventUtil.addHandler(item, "DOMNodeInsertedIntoDocument", function(event){
	    alert(event.type);
	    alert(event.target);
	});
    list.appendChild(item);
});

以上代码首先创建了一个包含文本"Item 4"的新<li>元素。由于 DOMSubtreeModified 和 DOMNodeInserted 事件是冒泡的,所以把它们的事件处理程序添加到了文档中

将列表项插入到其父节点之前,先将 DOMNodeInsertedIntoDocument 事件的事件处理程序添加给它。最后一步就是使用 appendChild()来添加这个列表项;此时,事件开始依次被触发

首先是在新<li>元素项上触发 DOMNodeInserted 事件,其 relatedNode 是<ul>元素。然后是触发新<li>元素上的 DOMNodeInsertedIntoDocument 事件,最后触发的是<ul>元素上的 DOMSubtreeModified 事件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值