JavaScript DOM-Event 事件
前端 JavaScript DOM 和 BOM 学习目录
4. DOM attribute property style属性 className属性 classList属性 Data
DOM-Event 认识事件
首先我们的一个页面的话都是需要进行和用户之间进行交互的,这个交互的过程就需要使用到我们的事件处理来实现
JavaScript 是可以实现针对事件编写对应的处理程序的(
handler)我们是可以实现的是将页面中的一些部分,用户进行某种处理后,就执行对应的某种代码功能体
我们的事件实现检测的方式含有:
- 在 HTML元素中直接实现监听(不推荐使用)
<button onclick="console.log("我被点击了")">按钮1</button>- DOM属性,通过元素的 on 来实现监听
- 通过 EventTargrt 对象中的 addEventListener 来实现监听
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <button>按钮1</button> <button>按钮2</button> <script> // 先实现获取我们的元素 btn = document.querySelectorAll("button") // on 的事件监听 btn[0].onclick = function () { console.log("我被点击了...") } btn[1].addEventListener('click', function () { console.log("我也被点击了") }) </script> </body> </html><!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <button>按钮1</button> <button>按钮2</button> <script> // 先实现获取我们的元素 btn = document.querySelectorAll("button") function handlerBtn01 () { console.log("我被点击了...") } function handlerBtn02 () { console.log("我也被点击了") } // on 的事件监听 btn[0].onclick = handlerBtn01 btn[1].addEventListener('click', handlerBtn02) </script> </body> </html>上面的就是我们的两中事件监听的不同的书写方法,一种就是回调函数的书写方式,后面就是我们的通过赋值在进行的我们的操作
addEventListener 可以实现的是我们的多同一个事件添加多个执行的回调函数,同时也可以实现随意的移除的操作
但是使用我们的 on 的监听事件的事件的时候,。就不是十分的好绑定以及移除了
addEventListener 是十分灵活的
DOM-Event 认识事件流
当我们在浏览器中实现点击一个元素的时候,我们点击的不仅仅是元素本身,实现点击的是我们的元素本身以及他的层级式的父元素
只要是含有层级关系,那么就会导致事件的上传,这个就是我们的事件冒泡
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> :root { --box-color: skyblue; --span-color: red; } body { padding: 0; margin: 0; .box { width: 200px; height: 200px; background-color: var(--box-color); display: flex; justify-content: center; align-items: center; // 回顾:flex 布局中的任何元素是不会再次区分块级和行内元素的 } span { height: 100px; width: 100px; background-color: var(--span-color); } } </style> </head> <body> <div class="box"> <span></span> </div> <script> var divEl = document.querySelector(".box") var spanEl = document.querySelector("span") window.addEventListener("click", () => { console.log("页面被点击了...") }) divEl.addEventListener('click', function () { console.log("div 被点击了...") }) spanEl.addEventListener('click', function () { console.log("span被点击了..") }) /** * 这个时候我们就会发现一点,当点击我们的 spanEL 的时候,我们是会触发上面两级事件触发的 * 当我们实现点击 divEL 的时候,我们就会发现, div 和 window 的事件被触发了 * 当我们实现点击页面的时候, 就只触发本身,因为上面没有闹大了,哈哈 */ </script> </body> </html>点击我们的 span 的时候,就会触发本身的事件,以及 divEl 的事件,和我们的 window 的事件
点击我们的 div 的时候,就会触发本身以及 window
点击 window 的时候,就只是触发本身
这个就是我们的事件往上实现传递,这个传递的顺序就是我们的事件流
DOM-Event 事件冒泡和事件捕获
从我们的元素的最内层往上传递的顺序,这个顺序就是我们的 事件冒泡(Event Bubble)
从我们的最外层向最内层实现传递的顺序就是我们的 事件捕获(Event Capture)
我们的一个网页中的默认的事件流是我们的 —— 事件冒泡
但是只不过还是可以通过某种手段实现我么的 —— 事件捕获
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> :root { --box-color: skyblue; --span-color: red; } body { padding: 0; margin: 0; .box { width: 200px; height: 200px; background-color: var(--box-color); display: flex; justify-content: center; align-items: center; // 回顾:flex 布局中的任何元素是不会再次区分块级和行内元素的 } span { height: 100px; width: 100px; background-color: var(--span-color); } } </style> </head> <body> <div class="box"> <span></span> </div> <script> var divEl = document.querySelector(".box") var spanEl = document.querySelector("span") /** * addEventListener * @param {string} type 指定事件类型 * @param {function} listener 就是我们的handler处理事件函数 * @param {boolean} options 选择我们的事件流模式, 默认是事件冒泡模式,true就是表示事件捕获 */ spanEl.addEventListener("click", function (e) {}, true) </script> </body> </html>注意我们的事件冒泡和事件捕获只是事件流的两种不同表现形式
实现我们的进行添加用户的交互功能的实现的时候,就是使用的是我们的
element.onclick = handlerhandler 就是用来实现处理用户的事件交互的执行函数的
element.addEventListener(type, handler[, options])handler 就是回调函数,options 就是实现的用来选择事件流模式的
DOM-Event 事件对象常用属性
我们的页面实现一些特定的交互的时候,这些交互的事件就是默认的被浏览器包含在了特定的对象中,这个对象就是 Event 对象
在这个对象中有我们的很多的页面的交互实现
获取我们的事件的信息的时候,我们就是通过的是在进行事件监听的时候,传入一个参数,这个参数就是我们的事件参数
一般的规范化的书写格式就是我们的 event 或者 e
我们是可以通过这个参数来获取很多的信息的
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="box"> <span></span> </div> <script> var divEl = document.querySelector(".box") // 开始实现使用我们的事件对象 // 就是我们的这个函数是可以实现接收一个参数 divEl.addEventListener("click", function (event) { console.log("事件对象内容为: ${event}") }) </script> </body> </html>
event 对象中常使用的属性
属性 描述 实例 type 实现获取事件对应的类型 event.type target 当前事件发生的元素 event.target currentTarget 当前处理事件的元素 event.currentTarget eventPhase 事件所处的阶段 event.eventPhase ***offsetX offsetY*** 是西安发生在元素内的位置 event.offsetY ***clientX clientY*** 事件发生在客户端的位置 event.clientX ***pageX pageY*** 事件发生在客户端相对于页面的位置 event.pageX ***screenX screenY*** 事件发生在相对于屏幕的位置 event.screenX divEl.addEventListener("click", function (event) { console.log(`事件类型: ${event.type}`) console.log(`事件阶段: ${event.eventPhase}`) })target : 就是我们发生事件的元素对象,同样可以实现触发该事件的其他元素(事件冒泡)
currentTarget : 就是我们的设置事件的对象,这个是一直不变的
DOM-Event 事件对象常用方法
**event.preventDefault() **实现的是阻止默认行为,就是可以实现的就是我们的阻止浏览器默认行为
**event.stopPropagation() **就是实现的是阻止我们的事件流的继续传递
DOM-Event 事件中的 this
首先我们的函数的调用的时候, this 的指向就是我们的 window 全局对象
当我们的函数在事件处理的时候,this的指向就是我们的该元素,是谁进行的处理我们的 handler,那么我们的 this 就是实现指向谁
同时我们在后面还是会学习一些关于改变 this 指向的方法函数的,这个时候我们的 this 的指向就会人为的发生变动
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="box"> <span></span> </div> <script> var divEl = document.querySelector(".box") // 开始实现使用我们的事件对象 // 就是我们的这个函数是可以实现接收一个参数 divEl.addEventListener("click", function (event) { console.log(this) console.log(event.currentTarget) console.log(divEl) console.log(divEl === this) // true }) </script> </body> </html>
DOM-Event EventTarget类
首先我们需要注意的是,我们的页面中的所有的类都是继承的是我们的这个类来实现的
继承的好处就是我们的: 可以实现我们的代码的复用率的提高
所以说我们的这个类中具有的所有的方法,在我们的每一个元素中都是可以实现使用的
事实上的话,我们的 window 对象也是继承是我们的 EventTarget 这个类的
EventTarget 就是我们的一个DOM 接口,主要是用于我们的添加、删除、派发Event事件的
方法 描述 addEventListener 实现的是为某个元素注册某个事件类型以及事件处理函数 removeEventListener 实现的是为某个元素移除某个事件以及事件处理函数 dispatchEvent 实现的是将某个对象类型派送到 EventTarget 上面实现使用 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .box { width: 100px; height: 100px; background-color: skyblue; } </style> </head> <body> <div class="box"></div> <script> var divEl = document.querySelector(".box") // 开始实现使用我们的事件对象 // 就是我们的这个函数是可以实现接收一个参数 var foo = function (event) { console.log("我被电击了") } divEl.addEventListener("click", foo) setTimeout(function () { divEl.removeEventListener("click", foo) alert("事件监听已被移除")} , 3000) </script> </body> </html>dispatchEvent 就是实现的是我们的自定义一个事件
dispatchEvent(new Event("juwenzhang"))
element.addEventListener("juwenzhang", handler)
DOM-Event 事件委派 event delegation
使用我们的事件委托就是为了解决: 当含有多个元素需要做一些相同的事情的时候,这个时候就可以使用我们的事件委托来实现
提高代码的复用率,就是我们在子类中会发生的相同的事件直接在父类中实现即可,然后通过事件委托来实现委派即可
来一个十分清晰的例子吧:
玩过爬虫的都知道,有时间我们是会对我们的一个端口发送客户端请求,然后获取其返回的数据
但是这个时候,我们实现发送网络请求的时候,多次请求这个时候就会发生自己的 ip地址被封的风险
为了避免这个现象的出现,我们就可以使用代理,使用代理的 ip地址来帮我们发送相应的请求,获取我们的返回数据即可
开始实现我们的最原生的写法
即是说每一个li 都实现监听自己的函数点击事件
<!-- 第一种实现形式, 通过this 实现获取本身元素 --> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .active { color: red; font-weight: bold; text-decoration: underline; cursor: pointer; font-size: 20px; } .non-active { color: black; } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> <script> var liEls = document.querySelectorAll("li") for (let item of liEls) { console.log(item) item.onclick = function () { for(let item01 of liEls) { try { item01.classList.remove("active") } catch (e) { console.log(e) } finally { item01.classList.add("non-active") } } this.classList.remove("non-active") this.classList.add("active") } } </script> </body> </html><!-- 第二种实现形式,通过 event.currentTarget 获取本身元素 --> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .active { color: red; font-weight: bold; text-decoration: underline; cursor: pointer; font-size: 20px; } .non-active { color: black; } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> <script> var liEls = document.querySelectorAll("li") for (let item of liEls) { console.log(item) item.onclick = function (event) { for(let item01 of liEls) { try { item01.classList.remove("active") } catch (e) { console.log(e) } finally { item01.classList.add("non-active") } } event.currentTarget.classList.remove("non-active") event.currentTarget.classList.add("active") } } </script> </body> </html>使用事件委派来实现
就是通过我们的 ul来实现监听事件
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .active { color: red; font-weight: bold; text-decoration: underline; cursor: pointer; font-size: 20px; } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> <script> var ulEl = document.querySelector("ul") ulEl.onclick = function (event) { for (var i = 0; i < ulEl.children.length; i++) { ulEl.children[i].classList.remove('active') } if (event.target === event.currentTarget) { return } event.target.classList.add("active") } </script> </body> </html><!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="box"> <button>添加</button> <button>移除</button> <button>搜索</button> </div> <script> var divEl = document.querySelector(".box") divEl.onclick = function (event) { if(event.target === event.currentTarget) { return } console.log(`点击了${event.target.textContent}按钮`) } </script> </body> </html>
有可能从现在开始,书写的有一些代码使用了 let 或者说 const,从严格意义上来讲,这两个关键字应该出现在 es6 里面出现的
但是为了后期的过渡的实现,我们从现在就开始慢慢转变使用 es6 的一些关键字了
现在的话,我们还是在使用我们的 es5 哟,注意!!!