以下大部分为学习《JavaScript 高级程序设计》(第 3 版) 所做笔记。
目录:
1. 了解 UI 事件
2. load 事件
3. unload 事件
4. resize 事件
5. scroll 事件
Q: UI 是什么意思?
A: UI 是 User Interface 的缩写,意思是用户界面。
Q: 什么是 UI 事件?
A: UI 事件指的是那些不一定与用户操作有关的事件。
Q: UI 事件什么时候会被触发?
A: 当用户与页面上的元素交互时触发。
Q: UI 事件有哪些?
A: DOMActivate load unload abort error select resize scroll
Q: 何时会在何处触发 load 事件?
A: 页面完全加载后(包括所有图像、JavaScript文件、CSS文件等外部资源)在 window 上触发,当所有框架都加载完毕时在框架上面触发,当图像加载完毕时在 <img> 元素上面触发。
定义 onload 事件处理程序的方式
第一种方式:通过 JS 来指定事件处理程序的方式。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script> var EventUtil = { //视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件 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; } }, //返回对 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){ if(element.removeEventListener){ element.removeEventListener(type, handler, false) }else if(element.detachEvent){ element.detachEvent("on"+type, handler); }else{ element["on"+type] = null; } }, //阻止事件流 //因为 IE不支持事件捕获,所以在跨浏览器情况下也只能用于阻止事件冒泡 stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } } }; EventUtil.addHandler(window, "load", function(event){ console.log("loaded"); }) </script> </body> </html>
(跨浏览器对象 EventUtil :https://www.cnblogs.com/xiaoxuStudy/p/13131725.html#three )
控制台输出:
第二种方式:为 <body> 元素添加一个 onload 特性
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body onload="console.log('loaded')"> </body> </html>
控制台输出:
🔹 根据 "DOM2 级事件" 规范,应该在 document 而非 window 上面触发 load 事件。但是,所有浏览器都在 window 上面实现了该事件,以确保向后兼容。
🔹 因为在 HTML 中无法访问 window 元素,所以在 window 上发生的任何事件都可以在 <body> 元素中通过相应的特性来指定。
图像上触发onload事件
方式1:在 HTML 中为图像指定 onload 事件处理程序
下面例子实现图片加载完毕之后控制台输出“图片加载完毕”。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <img src="pic.jpg" onload="console.log('图片加载完毕')"> </body> </html>
图片加载完毕后触发图像上面的 onload 事件,控制台打印"图片加载完毕"。
方式2:通过 JS 为图像指定事件处理程序
下面例子实现图片加载完毕之后在控制台输出图片的src。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <img src="pic.jpg" id="pic1"> <script> //跨浏览器对象 EventUtil var EventUtil = { //视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件 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; } }, //返回对 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){ if(element.removeEventListener){ element.removeEventListener(type, handler, false) }else if(element.detachEvent){ element.detachEvent("on"+type, handler); }else{ element["on"+type] = null; } }, //阻止事件流 //因为 IE不支持事件捕获,所以在跨浏览器情况下也只能用于阻止事件冒泡 stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } } }; //取得图片的引用 var image = document.getElementById("pic1"); //添加load事件,注册到image上 EventUtil.addHandler(image, "load", function(event){ event = EventUtil.getEvent(event); console.log(EventUtil.getTarget(event).src); }) </script> </body> </html>
🔹 新图像元素不一定要从添加到文档后才开始下载,只要设置了 src 属性就会开始下载。
实现:预先加载图像,再添加 onload 事件,再为图片设置 src
方式1:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script> //跨浏览器对象 EventUtil var EventUtil = { //视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件 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; } }, //返回对 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){ if(element.removeEventListener){ element.removeEventListener(type, handler, false) }else if(element.detachEvent){ element.detachEvent("on"+type, handler); }else{ element["on"+type] = null; } }, //阻止事件流 //因为 IE不支持事件捕获,所以在跨浏览器情况下也只能用于阻止事件冒泡 stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } } }; //为 window 指定 onload 事件处理程序 //确保往 DOM 中添加新元素之前页面已经加载完毕,如果在页面加载完毕之前操作 document.body 会出错 EventUtil.addHandler(window, "load", function(){ //创建一个图片元素 var image = document.createElement("img"); //为 image 指定 onload 事件 //图片加载完毕之后给出提示,控制台输出 src 作为提示 EventUtil.addHandler(image, "load", function(){ event = EventUtil.getEvent(event); console.log(EventUtil.getTarget(event).src); }); //添加节点 image document.body.appendChild(image); //设置图像的 src //新图像元素不一定要从添加到文档后才开始下载,只要设置了 src 属性就会开始下载 image.src = "pic.jpg"; }) </script> </body> </html>
方式2 : 使用 DOM0 级的 Image 对象实现
❔ 不知道哪里出问题了,图片没显示出来...
为 <script> 元素指定事件处理程序
用处:开发人员确定动态加载的 JS 文件是否加载完毕
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script> //跨浏览器对象 EventUtil var EventUtil = { //视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件 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; } }, //返回对 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){ if(element.removeEventListener){ element.removeEventListener(type, handler, false) }else if(element.detachEvent){ element.detachEvent("on"+type, handler); }else{ element["on"+type] = null; } }, //阻止事件流 //因为 IE不支持事件捕获,所以在跨浏览器情况下也只能用于阻止事件冒泡 stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } } }; //为 window 指定 onload 事件处理程序 EventUtil.addHandler(window, "load", function(){ //创建一个 <script> 元素 var script = document.createElement("script"); //为 script 指定 onload 事件处理程序 EventUtil.addHandler(script, "load", function(){ //script 加载完毕之后在控制台输出提示 console.log("JS文件加载完毕"); }); //设置 script 的 src script.src="test.js"; //将 script 添加到文档中 document.body.appendChild(script); }) </script> </body> </html>
🔹 只有在设置了 <script> 元素的 src 属性并将该元素添加到文档后,才会开始下载 JS 文件。也就是说对于<script>元素而言,指定 src 属性和指定事件处理程序的先后顺序不重要了。
🔹 大多数浏览器中 event 对象的 target 属性引用的是 <script> 节点,在 Firefox3 之前引用的是 document。
🔹 IE8 及更早版本不支持 <script> 元素上的 load 事件。
为 <link> 元素指定事件处理程序
用处:开发人员确定样式表是否加载完毕
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script> //跨浏览器对象 EventUtil var EventUtil = { //视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件 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; } }, //返回对 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){ if(element.removeEventListener){ element.removeEventListener(type, handler, false) }else if(element.detachEvent){ element.detachEvent("on"+type, handler); }else{ element["on"+type] = null; } }, //阻止事件流 //因为 IE不支持事件捕获,所以在跨浏览器情况下也只能用于阻止事件冒泡 stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } } }; //为 window 指定 onload 事件处理程序 EventUtil.addHandler(window, "load", function(){ //创建一个 <link> 元素 var link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; //为 link 指定 onload 事件处理程序 EventUtil.addHandler(link, "load", function(){ //link 加载完毕之后在控制台输出 console.log("样式表加载完毕"); }); //设置 link 的 href link.href = "test.css"; //将 link 添加到文档中 document.body.appendChild(link); }) </script> </body> </html>
🔹 在未指定 href 属性并将 <link> 元素添加到文档之前不会开始下载样式表
🔹 支持的浏览器:IE、Opera
Q: 何时在何处会触发 unload 事件?
A: 文档被完全卸载后在 window 上面触发 unload 事件,当所有框架都卸载后在框架集上触发,当嵌入的内容卸载完毕后在 <object> 元素上触发。只要用户从一个页面切换到另一个页面,就会发生 unload 事件。
Q: 什么情况需要用到 unload 事件?
A: 清除引用的时候。清除引用避免内存泄漏。
指定 onunload 事件处理程序的方式
方式1: 通过 JS 来指定事件处理程序
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script type="text/javascript" src="EventUtil.js"></script> <script> //为 window 指定 onunload 事件处理程序 EventUtil.addHandler(window, "unload", function(){ alert("unloaded"); }) </script> </body> </html>
方式2:为 <body> 元素添加一个 onunload 特性
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body onunload="alert('unloaded')"> </body> </html>
❔ 在浏览器运行方式1跟方式2的代码,尝试了点击链接、关闭浏览器窗口、重新载入页面,不知道为什么都没有触发 unload 事件。
🔹 为了确保向后兼容,所有浏览器都在 window 上实现了 unload 事件。即使,根据"DOM2级事件",应该在 <body> 元素而非 window 对象上触发 unload 事件。
Q: 什么情况会触发 resize 事件?
A: 当浏览器窗口被调整到一个新的高度或宽度时会触发。浏览器窗口最大化或最小化也会触发。
Q: 何时会触发 resize 事件?
A: 不同浏览器有不同的机制。
▶ IE、Safari、Chrome、Opera:浏览器窗口变化了 1 像素时触发,然后随着变化不断触发
▶ Firefox:只会在用户停止调整窗口大小时才会触发
Q: 不同浏览器存在不同的机制,在进行开发时应该注意什么?
A: 应该注意不要在事件的处理程序中加入大计算量的代码,因为这些代码可能会被频繁执行,从而导致浏览器反应明显变慢。
Q: resize 事件在哪里触发?
A: window(窗口)上
指定 resize 事件处理程序的方式
方式1: 通过 JS 来指定事件处理程序
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script type="text/javascript" src="EventUtil.js"></script> <script> //为 window 指定 onresize 事件处理程序 EventUtil.addHandler(window, "resize", function(){ console.log("resized"); }) </script> </body> </html>
方式2:为 <body> 元素添加一个 resize 特性
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body onresize="console.log('resized')"> </body> </html>
Q: 在何时何处触发 scroll 事件?
A: scroll 事件是在 window 对象上发生的。当用户滚动带滚动条的元素中的内容时,在该元素上触发。<body> 元素中包含所加载页面的滚动条。
Q: scroll 事件表示什么?
A: 表示页面中相应元素的变化。
Q: 使用 scroll 事件时需要注意什么?
A: 与 resize 事件类似,scroll 事件也会在文档被滚动期间重复被触发,所以有必要保持事件处理程序的代码简单
指定 scroll 事件处理程序的方式
下例实现:滑动滚动条时,在框下文字动态提示滚动了多少次。
方式1: 通过 JS 来指定事件处理程序
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style> div{ border: 10px solid yellowgreen; width: 200px; height: 200px; overflow: scroll; } </style> </head> <body> <div id="div1"> 2020年5月30日,爱奇艺《青春有你第二季》总决赛举行。通过总决赛最后一次考核舞台现场,九名女团人选最终确定,她们分别是:刘雨昕、虞书欣、许佳琪、喻言、谢可寅、安崎、赵小棠、孔雪儿、陆柯燃,组合名称为“THE NINE”,代表独一无二的九人女团。 </div> <p>滚动<span id="scrollNum"> 0 </span>次</p> <script type="text/javascript" src="EventUtil.js"></script> <script> var div = document.getElementById("div1"); var x = 0; //为 div 指定 onscroll 事件处理程序 EventUtil.addHandler(div, "scroll", function(){ document.getElementById("scrollNum").innerHTML = x += 1; }) </script> </body> </html>
方式2: 为 <div> 元素添加一个 resize 特性
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style> div{ border: 10px solid yellowgreen; width: 200px; height: 200px; overflow: scroll; } </style> </head> <body> <div onscroll="fn()"> 2020年5月30日,爱奇艺《青春有你第二季》总决赛举行。通过总决赛最后一次考核舞台现场,九名女团人选最终确定,她们分别是:刘雨昕、虞书欣、许佳琪、喻言、谢可寅、安崎、赵小棠、孔雪儿、陆柯燃,组合名称为“THE NINE”,代表独一无二的九人女团。 </div> <p>滚动<span id="scrollNum"> 0 </span>次</p> <script> x = 0; function fn(){ document.getElementById("scrollNum").innerHTML = x += 1; } </script> </body> </html>