13. 事件
JavaScript与HTML之间的交互是通过事件实现的。可以使用侦听器预定事件。
在传统软件工程中被称为观察者模式。支持行为与外观间的松散耦合。
13.1 事件流
- 事件流描述的是从页面中接收事件的顺序    
- IE 事件冒泡流
 - NetscapeCommunicator 事件捕获流
 
 Event bubbling- 事件开始时由最具体的元素接受,然后逐级向上传递给较为不具体的节点
 - 现代浏览器,将事件一直冒泡到window对象
 
Event capturing- 不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件
 - 事件捕获的用意在于在事件到达预定目标之前捕获它。
 - DOM2规范要求事件应该从document开始传播,但浏览器都是从window开始捕获事件
 
- DOM2事件    
- 事件流三个阶段:      
- 事件捕获阶段
 - 处于目标阶段
 - 事件冒泡阶段
 
 
 - 事件流三个阶段:      
 
13.2 事件处理程序
- 事件就是用户或浏览器自身执行的某种动作。
 - 响应事件的函数就是事件处理程序
 
- HTML事件处理
 
<button onclick="alert('event')"></button>
  - DOM0事件处理
 
// 在事件流的冒泡阶段被处理
var button = document.getElementById('myBtn');
button.onclick = function(){
	alert(this.id); // "myBtn"
}
button.onclick = null;
  - DOM2事件处理
 
addEventListener()removeEventListener()- 接受三个参数:    
- 监听的事件名
 - 作为事件处理程序的函数
 - 调用处理函数的时机:
true捕获阶段,false冒泡阶段 
 - 【优势】可以添加多个事件处理程序
 - 匿名事件处理函数,将不会被移除
 
var button = document.getElementById('myBtn');
button.addEventListener('click', function(){
	alert(this.id);
}, false);
button.addEventListener('click', function(){
	alert('hello world');
}, false);
// 添加了两个事件处理程序,按照添加顺序依次执行
// 移除事件只能通过removeEventListener(name, handler, flag)
  大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。
最好只在需要在时间到达目标之前截获他的时候,将事件处理程序加到捕获阶段
- IE事件处理程序    
attachEvent()detachEvent()- 【差异】:      
- IE中事件名称带有
on-前缀,例如onclick - 触发顺序与添加顺序相反
 - 全局作用域中执行事件处理程序
 
 - IE中事件名称带有
 
 
13.3 事件对象
- 在DOM上触发某个事件时,会产生一个事件对象
event - 所有事件通用成员    
bubblescancelablecurrentTargetdefaultPreventeddetaileventPhase事件阶段1,2,3preventDefault()取消默认行为stopImmediatePropagationstopPropagation()targettrustedtypeview
 currentTarget事件处理程序注册在哪个元素上target事件真正的目标- 只有在事件处理程序执行期间,
event对象才会存在,执行完毕就会被销毁。 
13.***类型
- DOM3事件:    
- UI事件
 - 焦点,元素获得失去焦点
 - 鼠标
 - 键盘
 - 滚轮
 - 文本,输入文本
 - 合成,IME
input method editor - 变动
mutation底层DOM结构发生变化 
 - UI事件    
loadwindow/imgunload卸载aborterrorselectresizescroll
 - 焦点事件    
blur不冒泡focus元素获得焦点,但不冒泡focusin获得焦点,冒泡focusout冒泡
 - 鼠标与滚轮事件    
clickdbclickmousedown任意鼠标按钮按下mouseup按键释放mouseenter不冒泡mouseleave光标移动到元素范围之外,不冒泡mousemove鼠标指针在元素内部移动时重复触发mouseout鼠标指针移入另一个元素(可以是外部,也可是子元素)mouseover- 鼠标位置      
event.clientX客户区event.clientYevent.pageX页面event.pageYevent.screenX屏幕event.screenY
 - 修改键      
shift,ctrl,alt, meta:windows/cmd- DOM规定状态值
shiftKey,ctrlKey,altKey,metaKey 
 - 主目标和相关元素
event.relatedTargetmouseover事件主目标是获得光标的元素,相关元素是失去光标的元素mouseout事件主目标是失去光标的元素,相关元素是获得光标的元素
 - 鼠标按键
event.button- 0左键,1中键,2右键
 
 - 鼠标滚轮事件
mousewheelwheelDelta120的倍数,(+上-下)表示滚动方向
 
 - 键盘与文本事件    
keydownkeypresskeyupkeycode键码key键值textInputinputMethod- 能够区分键盘输入、粘贴、拖放、IME、手写、脚本等
 
 - 复合事件
composition event- 用于处理
IME的输入序列 IME通常需要同时按住多个键,最终只输入一个字符compositionstartcompositionupdatecompositionend
 - 用于处理
 - 变动事件    
- DOM发生变化时
 removeChild()/replaceChild()DOMNodeRemoved—>DOMNodeRemovedFromDocument—>DOMSubtreeModified
appendChild()/replaceChild()/insertBefore()DOMNodeInserted—>DOMNodeInsertedIntoDocument—>DOMSubtreeModified
 - HTML5事件    
contextmenubeforeunload卸载页面之前DOMContentLoaded在形成完整的DOM树之后就会触发,不理会图像、JavaScript、css文件是否已经下载完成readystatechangeuninitilizedloadingloadedinteractivecomplete
- 往返缓存 
back-forward cache可以使用户使用浏览器的后退和前进按钮时加快页面的转换速度 haschangeURL参数列表变化
 - 设备事件
device eventorientationchangewindow.orientatin0肖像模式90左旋90度-90右旋90度
MozOrientationdeviceorientation设备朝向devicemotion
 - 触摸与手势事件
Touch Eventstouchstarttouchmovetouchendtouchcancel
 
// 创建自定义上下文菜单
var menu = document.createElement("ul");
menu.innerHTML = ` <li> <a href="www.baidu.com" target="_blank">BaiDu</li> <li><a href="https://github.com/18202409203" target="_blank">Github</li> <li><a href="https://blog.csdn.net/pangji0417" target="_blank">CSDN</li> `;
menu.id = "myMenu";
menu.style.background = "#fff";
menu.style.border = "1px solid #000";
menu.style.color = "red";
menu.style.visibility = "hidden";
document.body.appendChild(menu);
function menuHandler(event){
	event.preventDefault();
	var mm = document.getElementById("myMenu");
	mm.style.left = event.clientX + 'px';
	mm.style.top = event.clientY + 'px';
	mm.style.position = 'absolute';
	mm.style.visibility = "visible";
}
function clickHandler(event){
	var mm = document.getElementById("myMenu");
	mm.style.visibility = 'hidden';
}
document.addEventListener("contextmenu", menuHandler);
document.addEventListener("click", clickHandler);
  13.5 内存和性能
- 事件委托    
- 不是为每个元素添加一个事件,因为会冒泡,所以只指定一个事件处理程序,在DOM树中尽量最高层次上管理某一类型的所有事件
 
 
<ul id="myLinks">
	<li id="goSomewhere">Go Somewhere</li>
	<li id="doSomething">Do Something</li>
</ul>
<script> var list = document.getElementById("myLinks"); list.addEventListener("click", handler); function handler(event){ var target = event.target; switch(target.id){ case "goSomewhere": // goSomewhere break; case "doSomething": // doSomething break; } } </script>
  - 空事件处理程序
dangling event handler- 如果带有事件处理程序的元素被
innerHTML删除,那么原来添加到元素中的事件处理程序很有可能无法被当作垃圾收回 
 - 如果带有事件处理程序的元素被
 
13.6 模拟事件
- DOM中的事件模拟    
document.createEvent(type)创建事件UIEventMouseEvent—>initMouseEvent()MutationEvent—>initMutationEvent()KeyboardEvent—>initKeyEvent()
initMouseEvent()设置事件type“click”bubblescancelableview-->document.defaultViewdetail--> 0screenX/screenY/clientX/clientYctrlKey/altKey/shitKey/metaKeybutton按下哪个鼠标键,默认0relatedTarget
initKeyEvent()type“keydown”bubblescancelableviewkey键码location键区modifiers修改键列表repeat按键次数
dispatchEvent()触发事件
 
// 模拟右键菜单事件
var e = document.createEvent("MouseEvent");
e.initMouseEvent("contextmenu", true,true,document.defaultView,
	 100, 100, 100, 100, false,false,false, false,2, null);
document.dispatchEvent(e);

京公网安备 11010502036488号