이벤트는 클릭, 더블 클릭, 마우스 오버 등 문서나 브라우저 창에서 발생하는 특정 상호 작용 순간입니다.
이벤트 흐름은 페이지에서 이벤트가 수신되는 순서, 또는 페이지에서 이벤트가 전파되는 순서를 설명합니다.
IE의 이벤트 흐름을 이벤트 버블링(event bubbling)이라고 합니다: 가장 구체적인 요소부터 이벤트가 실행된 후 윈도우까지 전파됩니다. 단계별 개체.
넷스케이프 팀이 제안한 이벤트 흐름을 이벤트 캡처(이벤트 캡처)라고 합니다. 가장 바깥쪽 창 개체에서 이벤트가 실행되기 시작하고 점차 전파됩니다. 가장 구체적인 요소로 아래쪽으로 이동합니다.
이 두 이벤트 스트림의 차이점을 설명하기 위해 작은 실험을 해보겠습니다.
// html 文档 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件流 实验</title> </head> <body> <p id="test" style="font-size:3em;">点我点我,我是p</p> </body> </html>
// 事件冒泡 var p = document.getElementById("test"); p.addEventListener("click",function(){ console.log("i am p"); }, false); document.body.addEventListener("click",function(){ console.log("i am body"); }, false); document.documentElement.addEventListener("click",function(){ console.log("i am html"); }, false); document.addEventListener("click",function(){ console.log("i am document"); }, false); window.addEventListener("click",function(){ console.log("i am window"); }, false);
点击p,控制端会打印如下: i am p i am body i am html i am document i am window
// 事件捕获 var p = document.getElementById("test"); p.addEventListener("click",function(){ console.log("i am p"); }, true); document.body.addEventListener("click",function(){ console.log("i am body"); }, true); document.documentElement.addEventListener("click",function(){ console.log("i am html"); }, true); document.addEventListener("click",function(){ console.log("i am document"); }, true); window.addEventListener("click",function(){ console.log("i am window"); }, true);
사진이 두번 가공되어 조금 보기 흉한점 양해 부탁드립니다!
rree이벤트 버블링과 이벤트 캡처는 완전히 반대되는 이벤트 흐름임을 알 수 있습니다.
보통 이벤트 버블링을 많이 사용하고, 이벤트 캡처는 특별한 상황에서만 사용합니다.
DOM2 레벨 이벤트에서 지정하는 이벤트 흐름에는 이벤트 캡처 단계, 대상 단계, 이벤트 버블링 단계의 세 단계가 포함됩니다.
아아아아이 사진은 책에서 직접 찍은 사진입니다. 스스로 두뇌를 구성하고 창 개체를 직접 추가하세요!
点击p,控制端会打印如下: i am window i am document i am html i am body i am p
이벤트 핸들러: 는 이벤트에 응답하는 함수를 의미합니다.
HTML 이벤트 핸들러
요소가 지원하는 각 이벤트는 해당 이벤트 핸들러와 동일한 이름을 가진 HTML 속성을 사용하여 지정할 수 있습니다.
// 事件冒泡和事件捕获混合一下 var p = document.getElementById("test"); p.addEventListener("click",function(){ console.log("i am p"); }, true); document.body.addEventListener("click",function(){ console.log("i am body"); }, false); // 改为在冒泡阶段调用事件处理程序 document.documentElement.addEventListener("click",function(){ console.log("i am html"); }, true); document.addEventListener("click",function(){ console.log("i am document"); }, true); window.addEventListener("click",function(){ console.log("i am window"); }, false); // 改为在冒泡阶段调用事件处理程序
요소에 이벤트를 추가할 때 이 방법을 사용하지 않는 것이 좋습니다. 이 방법은 HTML과 JavaScript 코드를 긴밀하게 결합시키고 분리를 준수하지 않는다는 큰 단점이 있기 때문입니다. 웹 디자인의 행동과 구조.
DOM0 레벨 이벤트 핸들러
각 요소(창 및 문서 포함)에는 onclick, onmouseup 등과 같은 자체 이벤트 핸들러 속성이 있습니다.
위 코드를 다음과 같이 다시 작성하세요.
点击p,控制端会打印如下: i am document i am html i am p i am body i am window
DOM2 레벨 이벤트 핸들러
DOM2 레벨 이벤트는 다음과 같이 두 가지 메소드를 정의합니다. 이벤트 핸들러 지정 및 제거 작업을 처리합니다: addEventListener() 및 removeEventListener().
두 메서드 모두 세 개의 매개변수가 있습니다. 첫 번째 매개변수는 이벤트 이름, 두 번째 매개변수는 이벤트 핸들러 기능, 세 번째 매개변수는 부울 값입니다. 이는 이벤트를 의미합니다. 버블링 단계에서 핸들러가 호출됩니다. 이 값이 true이면 캡처 단계에서 이벤트 핸들러가 호출된다는 의미입니다.
계속해서 위 코드를 다시 작성하세요.
// 情况一 <button onclick="alert('I am button!');">按钮</button> // 情况二 <button onclick="show();">按钮</button> <script> function show(){ alert("I am button!"); } </script>
DOM2 수준 메서드를 사용하여 이벤트 핸들러를 추가할 때의 주요 이점은 요소에 대해 여러 이벤트 핸들러를 추가할 수 있다는 것입니다.
addEventListener()로 추가된 이벤트 핸들러가 익명 함수인 경우, 이 이벤트 핸들러는 RemoveEventListener()로 삭제할 수 없습니다.
IE 이벤트 핸들러
IE8 이하 IE 버전은 이벤트 버블링만 지원하고, addEventListener()와 RemoveEventListener()는 지원하지 않지만, 두 가지를 구현합니다. attachEvent() 및 detachEvent() 두 가지 메서드와 유사한 메서드입니다. 이 두 가지 메소드에는 이벤트 이름(클릭이 아닌 onclick)과 이벤트 처리 함수라는 두 개의 매개변수만 있습니다.
attachEvent() 메소드를 사용할 경우 addEventListener()와 달리 이벤트 처리 함수가 전역 범위에서 실행되므로 이는 window와 동일하므로 특별한 주의가 필요합니다.
<button id="test">按钮</button> var button = document.getElementById("test"); button.onclick = function(){ // this 对象指向 button 元素 console.log(this); alert("I am button!"); }; /* 删除指定的事件处理程序 */ button.onclick = null;
프로그램을 IE8 브라우저와 호환되게 만들고 싶지 않다면 이 두 기능을 사용하지 마세요.
일부 특정 이벤트의 경우 브라우저에는 기본 동작이 있습니다. 예를 들어, 링크를 클릭하면 지정된 페이지로 이동하고, 마우스 오른쪽 버튼을 클릭하면 브라우저 오른쪽 클릭 메뉴가 표시되며, 양식을 작성할 때 Enter 키를 누르면 자동으로 서버에 제출됩니다.
기본 브라우저 동작과 버블링 동작은 독립적입니다. 기본 이벤트 동작을 취소해도 이벤트 버블링은 취소되지 않으며 그 반대의 경우도 마찬가지입니다. 동일한 요소에 대한 여러 이벤트 핸들러도 서로 독립적입니다.
var button = document.getElementById("test"); function show(){ // this 对象指向 button 元素 console.log(this); alert("I am button!"); } // 添加事件处理程序 button.addEventListener("click",show, false); button.addEventListener("click",function(){ alert("I am second alert!"); },false); // 删除事件处理程序 button.removeEventListener("click",show, false); // 删除成功 button.removeEventListener("click",function(){ // 删除失败 alert("I am second alert!"); },false);
참고: 이벤트-4. 브라우저 기본 동작-Yuqing
DOM에서 이벤트가 발생하면 해당 이벤트와 관련된 모든 정보를 포함하는 이벤트 객체 이벤트가 생성됩니다.
event 对象只存在于事件处理程序执行期间,一旦执行完毕,立即被销毁。
<p> <a id="test" href="http://baidu.com">点我点我,我是链接</a> </p> /* 下列 event 对象的属性和方法都是只读的 */ var link = document.getElementById("test"); link.onclick = function(event){ // 判断当前事件是否会向 DOM 树上层元素冒泡 console.log(event.bubbles); // 判断是否可以取消事件的默认行为 console.log(event.cancelable); // 使用该方法可以取消事件的默认行为(使用前提是 cancelable 属性的值为 true) event.preventDefault(); // 判断是否已经调用了 preventDefault() 方法(DOM3级事件新增) console.log(event.defaultPrevented); // 指向事件遍历 DOM 时,识别事件的当前目标对象 console.log(event.currentTarget); // 指向触发事件的对象 console.log(event.target); // 表示事件流当前处于哪一个阶段 // 值为 1 表示在捕获阶段,值为 2 表示处于目标阶段,值为 3 表示在冒泡阶段 console.log(event.eventPhase); // 返回一个字符串, 表示该事件对象的事件类型 console.log(event.type); // 立即停止当前事件在 DOM 层次中的传播,即取消进一步的事件捕获或冒泡 event.stopPropagation(); };
为了进一步说明 event.stopPropagation() 的运行效果,借用前面的代码,更改如下:
// 事件冒泡和事件捕获混合一下 var p = document.getElementById("test"); p.addEventListener("click",function(){ console.log("i am p"); }, true); document.body.addEventListener("click",function(){ console.log("i am body"); }, false); // 改为在冒泡阶段调用事件处理程序 document.documentElement.addEventListener("click",function(){ console.log("i am html"); event.stopPropagation(); // 立即停止事件在 DOM 中的传播 }, true); document.addEventListener("click",function(){ console.log("i am document"); }, true); window.addEventListener("click",function(){ console.log("i am window"); }, false); // 改为在冒泡阶段调用事件处理程序
点击p,控制端会打印如下: i am document i am html
看到了吧,后面元素的事件就不会被激发了。
UI 事件指的是简单的用户界面事件
load 事件:当页面所有资源(比如图像、css文件、js文件等资源)完全加载完毕后,就会触发 window 上面的 load 事件。
当然,我们也可以单独为某个元素设置 load 事件,比如为一个图片绑定这个事件,就可以检测这个图片是否加载完毕了。
<img id="myImg" src="1.jpg" / alt="JavaScript DOM 이벤트의 그래픽 코드에 대한 자세한 소개" > var img = document.getElementById("myImg"); img.onload = function(){ alert("Image loaded!"); };
scroll 事件:在文档被滚动期间,重复触发该事件。
window.onscroll = function(){ console.log("Scroll!"); };
焦点事件会在页面元素获得或失去焦点时触发。
注意:默认情况下,只有部分 html 元素能获得鼠标焦点(如 input,a),很大一部分 html 元素是不能获得鼠标焦点的(如 p,img),这些能够获得鼠标焦点的元素就是 focusable 元素。
不过,可以通过为这些默认没有焦点事件的元素添加一个 tabindex 属性,从而使它可以支持焦点事件。
document.activeElement:返回当前页面中获得焦点的元素,如果没有某个元素获得焦点,则该属性的值为当前页面中的元素
document.hasFocus():判断当前文档或者当前文档的子节点是否获得了焦点
HTMLElement.focus():使得指定的元素获得焦点(前提是这个元素是一个可以获得焦点的元素)
HTMLElement.blur():移除当前元素获得的焦点
上面是一些 HTML5 中添加的焦点管理 API。下面说焦点事件:
focus 事件:在元素获得焦点时触发,这个事件不会冒泡
blur 事件:在元素失去焦点时触发,这个事件不会冒泡
focusin 事件:在元素获得焦点时触发,与 focus 事件等价,但会冒泡
focusout 事件:在元素失去焦点时触发,与 blur 事件等价,但会冒泡
<img id="img" src="1.jpg" tabindex="1" / alt="JavaScript DOM 이벤트의 그래픽 코드에 대한 자세한 소개" > var img = document.getElementById("img"); document.body.onscroll = function() { img.blur(); }; img.onfocus = function() { console.log("Img focused!"); }; img.onblur = function() { console.log("Img lose focus!"); }; img.onclick = function() { console.log(document.activeElement); console.log(document.hasFocus()); };
注意: focusin 和 focusout 事件,所有的 Firefox 版本都不支持,看这里。chrome 和 safari 中只有通过 addEventListener 方式绑定这两个事件才能正常使用,其他方式绑定都不行。
说说focus /focusin /focusout /blur 事件(推荐)
(WHATWG)Focus management APIs
DOM3 级事件中定义了9个鼠标事件。
<body> <p id="test"> <button>按钮</button> </p> </body> // css p { width: 300px; height: 300px; margin: 50px auto; border: 1px solid #aaa; }
mouseover 事件:鼠标指针首次进入一个元素边界之内时触发,会冒泡
mouseout 事件:鼠标指针移出这个元素边界时触发,会冒泡
var test = document.getElementById("test"); test.onmouseover = function(event){ event.target.style.border = "3px solid #666"; }; test.onmouseout = function(event){ event.target.style.border = "none"; };
mouseenter 事件:鼠标指针首次移动到元素范围之内时触发,不冒泡
mouseleave 事件:鼠标指针移动到元素范围之外时触发,不冒泡
var test = document.getElementById("test"); test.onmouseenter = function(event){ event.target.style.border = "10px solid #666"; }; test.onmouseleave = function(event){ event.target.style.border = "none"; };
mousemove 事件:当鼠标在元素内部移动时重复触发,会冒泡
// 这里写一个鼠标在 body 内移动时,背景颜色随机变化的脚本 document.body.onmousemove = function(){ var r = Math.floor(Math.random() * 256) g = Math.floor(Math.random() * 256) b = Math.floor(Math.random() * 256); document.body.style.background = "rgb("+r+","+g+","+b+")"; };
mousedown 事件:用户通过按下任意鼠标按钮时触发
mouseup 事件:用户释放鼠标按钮时触发
click 事件:用户单击鼠标左键时或按下回车键时触发
dblclick 事件:用户双击鼠标左键时触发
var body = document.body; body.onmousedown = function(){ console.log("Mouse down!"); }; body.onmouseup = function(){ console.log("Mouse up!"); }; body.onclick = function(){ console.log("One click!"); }; body.ondblclick = function(){ console.log("Double click!"); };
// 双击 body,控制端打印: Mouse down! Mouse up! One click! Mouse down! Mouse up! One click! Double click!
只有在同一个元素上相继触发 mousedown 和 mouseup 事件,才会触发 click 事件,缺一不可。类似地,只有连续触发两次 click 事件,才会触发 dblclick 事件。
获取点击坐标
clientX 和 clientY:鼠标指针在视口中的坐标
pageX 和 pageY:鼠标指针在页面中的坐标
screenX 和 screenY:鼠标指针在屏幕中的坐标
在页面没有滚动的情况下,pageX 和 pageY 的值与 clientX 和 clientY 的值相等。
document.body.onclick = function() { console.log("Client: " + "(" + event.clientX + "," + event.clientY + ")"); console.log("Page: " + "(" + event.pageX + "," + event.pageY + ")"); console.log("Screen: " + "(" + event.screenX + "," + event.screenY + ")"); };
keydown 事件:当用户按下任意键时触发,而且如果按住不放的话,会重复触发此事件
keypress 事件:当用户按下任意字符键时触发,而且如果按住不放的话,会重复触发此事件
keyup 事件:当用户释放键盘上的按键时触发
在用户按下一个字符键并且立马释放这个按键的过程中,先触发 keydown 事件,再触发 keypress 事件,最后触发 keyup 事件。
window.onkeydown = function() { console.log("on key down"); }; window.onkeyup = function() { if (event.keyCode === 65) { console.log(event.key); } console.log("one key up"); }; window.onkeypress = function() { console.log("one key press"); };
为了知道自己按下的是哪个按键,可以使用 event.which 来获得你按下按键的键码(比如字母 A 的键码为 65)。也可以通过键码属性(event.keyCode)来对特定的按键来进行响应。键码参考表
发生 keypress 事件时,会存在一个 charCode 属性,返回这个按键代表字符的 ASCII 编码。ASCII table
event.which 返回一个 keyCode 或 charCode 值,详情看下面代码
String.fromCharCode() 静态方法可以将 event.which 转化为相应的字符。
// 请自行粘贴复制于浏览器控制端测试 // 分别输入 a 和 A // A和a 的 ASCII码分别为65,97 window.onkeydown = function(){ if(event.keyCode === 65){ console.log("(keydown keyCode)You press 'a' or 'A'!"); } if(event.charCode === 65){ console.log("(keydown charCode)You press 'A'!"); } console.log("keydown event.which = " + event.which); console.log("(keydown:)" + String.fromCharCode(event.which)); }; window.onkeypress = function(){ if(event.keyCode === 65){ console.log("(keypress keyCode)You press 'A'!"); } if(event.charCode === 65){ console.log("(keypress charCode)You press 'A',not 'a'!"); } console.log("keypress event.which = " + event.which); console.log("(keypress:)" + String.fromCharCode(event.which)); };
在 DOM3 级事件中,做了一些变化,不再推荐使用 keyCode、charCode、which 属性,而是出现了两个新属性:
key
和char
,用来替代keyCode
和charCode
属性。但是不建议使用 key、char 属性,因为有一部分浏览器对他支持的不是很好。点这里
参考:JavaScript 事件——“事件类型”中“键盘与文本事件”的注意要点
变动事件是在 DOM 结构发生变化时触发
在 DOM2 中定义了多个变动事件,但是在 DOM3 中又废除了一些,在这里先简单提一下有这个东西,以后用到再作补充。
contextmenu 事件:单击鼠标右键,会触发这个事件并调出页面的上下文菜单。这个事件是鼠标事件的一种,并且支持冒泡。
在上面的例子中,我们演示了利用 contextmenu 事件来设置自定义右键菜单,以及屏蔽右键菜单。
然而,屏蔽右键菜单却难不倒高手,Greasy Fork 上面有一个脚本(网页限制解除),专门来打破对右键菜单有限制的页面。
beforeunload 事件:当浏览器窗口,文档或其资源将要卸载时或者刷新页面时,会触发这个事件【MDN】
下面有几点需要注意一下:
1. 如果处理函数为 Event 对象的 returnValue 属性赋值非空字符串,浏览器会弹出一个对话框,来询问用户是否确定要离开当前页面。没有赋值时,该事件不做任何响应。
2. 从2011年5月25号开始,HTML5规范指出在此事件处理函数中,对于window.alert(), window.confirm(), 和 window.prompt() 的调用会被忽略。
3. 旧版本的浏览器可能会在提示框里显示返回的信息,但是新版本浏览器都默认采用浏览器内设的提示信息。
// 复制粘贴于浏览器控制端,然后关闭页面,会出现提示框 window.addEventListener("beforeunload", function() { var message = "你真的要离开吗?"; event.returnValue = message; return message; }, false);
DOMContentLoaded 事件:在页面文档形成完整的 DOM 树时触发,不理会图像、js文件、css文件等资源是否加载完毕
这个事件可以为 document 或 window 绑定,但实际目标是 document。这个事件会冒泡。
注意:这个事件与 load 事件是不一样的,正常情况下,会早于 load 事件被触发。
感觉篇幅太长了,事件委托、移动设备中的事件、事件对内存性能的影响等内容将在以后逐渐写出。
以上就是JavaScript DOM 事件初探的图文代码详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!