JS中的事件

Posted 劳埃德·福杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS中的事件相关的知识,希望对你有一定的参考价值。

目录

1.简介

javascripthtml 的交互是通过事件实现的。
事件流描述了页面接收事件的顺序。
IE 开发了事件冒泡流,而 Netscape Communicator开发了事件捕获流

2.事件冒泡和事件捕获

事件冒泡:从最具体的元素(文档树中最深的节点)开始触发,然后向上传播。
事件捕获:最外层的节点最先收到事件,而最具体的节点应该最后收到事件。

<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>

 在点击页面中的 <div> 元素后,事件冒泡

 事件捕获

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

3.事件处理程序

事件意味着用户或浏览器执行的某种动作。比如,单击、加载、鼠标悬停。
为响应事件而调用的函数被称为事件处理程序(或事件监听器)
事件处理程序的名字以 "on" 开头,因此 click 事件的处理程序叫作 onclick ,而 load 事件的处理程序叫作 onload 。

①HTML事件处理程序

将可执行的JS代码赋值给html元素中的属性

<input type="button" value="Click Me" onclick="console.log('Clicked')"/>

有一个特殊的局部变量 event ,其中保存了 event 对象 

<!-- 输出"click" -->
<input type="button" value="Click Me" onclick="console.log(event.type)">

this 值相当于事件的目标元素 

<!-- 输出"Click Me" -->
<input type="button" value="Click Me" onclick="console.log(this.value)">

事件处理程序的代码不必引用表单元素就可以直接访问同一表单中的其他成员

<form method="post">
    <input type="text" name="username" value="">
    <input type="button" value="Echo Username" onclick="console.log(username.value)">
</form>

 缺点:
①存在一个时差问题。因为用户可能会在 HTML 元素一出现在页面上就触发相应
的事件,但当时的事件处理程序有可能尚不具备执行条件。
②事件处理程序的作用域链在不同浏览器中会导致不同结果。
③HTML 与 JavaScript 代码紧密耦合。如果要更换事件处理程序,就要改动两个地方:HTML 代码和 JavaScript 代码。

②DOM0事件处理程序

通过JS,将一个函数赋值给一个事件处理程序属性

let btn = document.getElementById("myBtn");
btn.onclick = function() 
    console.log("Clicked");
;

删除通过 DOM0 级方法指定的事件处理程序 

btn.onclick = null; // 移除事件处理程序

③DOM2事件处理程序

定义了两个方法,用于创建和删除事件处理程序的操作:addEventListener()和removeEventListener() 
接受 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。
true 表示在捕获阶段调用事件处理程序, false (默认值)表示在冒泡阶段调用事件处理程序。

使用 DOM2方式的主要优势是可以为同一个事件添加多个事件处理程序。

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

这里只能使用 removeEventListener()移除事件处理程序,这意味着使用 addEventListener() 添加的匿名函数无法移除。

④IE事件处理程序

IE 实现了与 DOM 中类似的两个方法:attachEvent()和 detachEvent()
这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() 
    console.log("Clicked");
);

⑤跨浏览器事件处理程序,兼容 DOM0 级方法、DOM2 级方法、 IE 方法

自定义 EventUtil 对象

var EventUtil = 
    addHandler: function(element, type, handler) 
        if (element.addEventListener) 
            element.addEventListener(type, handler, false);
         else if (element.attachEvent) 
            element.attachEvent("on" + type, handler);
         else 
            element["on" + type] = handler;
        
    ,
    removeHandler: function(element, type, handler) 
        if (element.removeEventListener) 
            element.removeEventListener(type, handler, false);
         else if (element.detachEvent) 
            element.detachEvent("on" + type, handler);
         else 
            element["on" + type] = null;
        
    
;
let btn = document.getElementById("myBtn")
let handler = function() 
    console.log("Clicked");
;
EventUtil.addHandler(btn, "click", handler);

4.事件对象

在触发 DOM 上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。 

在事件处理程序内部, this 对象始终等于 currentTarget 的值,而 target 只包含事件的实际目标。 

let btn = document.getElementById("myBtn");
// 在按钮上添加单击处理程序,click 事件的目标是按钮
btn.onclick = function(event) 
    console.log(event.currentTarget === this); // true
    console.log(event.target === this); // true
;
// 在document.body上添加单击处理程序
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
;

type 属性在一个处理程序处理多个事件时很有用

let btn = document.getElementById("myBtn");
let handler = function(event) 
    switch(event.type) 
        case "click":
            console.log("Clicked");
            break;
        case "mouseover":
            event.target.style.backgroundColor = "red";
            break;
        case "mouseout":
            event.target.style.backgroundColor = "";
            break;
    
;
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;

preventDefault() 方法用于阻止特定事件的默认动作
比如,链接的默认行为就是在被单击时导航到 href 属性指定的 URL。
如果想阻止这个导航行为,可以在 onclick 事件处理程序中取消。

let link = document.getElementById("myLink");
link.onclick = function(event) 
    event.preventDefault();
;

stopPropagation() 方法用于立即阻止事件流在 DOM 结构中传播,取消后续的事件捕获或冒泡
例如,直接在按钮的事件处理程序中调用 stopPropagation() ,可以阻止document.body上注册的事件处理程序执行。

let btn = document.getElementById("myBtn");
btn.onclick = function(event) 
    console.log("Clicked");
    event.stopPropagation();
;
document.body.onclick = function(event) 
    console.log("Body clicked");
; 

eventPhase 属性可用于确定事件流当前所处的阶段。
如果事件处理程序
在捕获阶段被调用,则eventPhase 等于 1
在目标上被调用,则 eventPhase 等于 2
在冒泡阶段被调用,则 eventPhase 等于 3

跨浏览器的事件对象

var EventUtil = 
    addHandler: function(element, type, handler) 
        // 为节省版面,删除了之前的代码
    ,
    // 返回对 event 对象的引用
    getEvent: function(event) 
        return event ? event : window.event;
    ,
    // 返回事件目标
    getTarget: function(event) 
        return event.target || event.srcElement;
    ,
    // 阻止事件的默认行为
    preventDefault: function(event) 
        if (event.preventDefault) 
            event.preventDefault();
         else 
            event.returnValue = false;
        
    ,
    removeHandler: function(element, type, handler) 
        // 为节省版面,删除了之前的代码
    ,
    // 停止事件冒泡
    stopPropagation: function(event) 
        if (event.stopPropagation) 
            event.stopPropagation();
         else 
            event.cancelBubble = true;
        
    
;

以上是关于JS中的事件的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式用于在不被单引号或双引号包围时使用空格分割字符串

认识EasyUI——DataGrid的onClickRow事件

js offsetHeight offsetWidth 解说

Xamarin.iOS 的鍵盤控制 (AutoLayout 與 新的 Keyboard 事件 )

Markdown,让你印象笔记中的图片版面更好看

剑指offer第二版面试题4:替换空格(JAVA版)