优快云话题挑战赛第2期
参赛话题:前端技术分享
Web APIs基础学习四
在前三节的介绍中,主要学习了 对象 与 事件以及相关的 DOM操作 。其中 DOM 操作的主要核心就是 对象操作 和 事件操作 ;在事件操作的语法结构中,基本都是:事件源.事件类型 = 事件处理程序
,这也是事件的三个要素 :事件源(谁) ,事件类型(要干什么 ,是点击 还是鼠标经过 ,亦或者是键盘弹起时候要干什么),事件处理程序(怎么去干);
对于事件操作,其实在很多项目的开发过程中,都会设计到判断用户操作事件的模块,其主要目的也 为了根据用户所进行的事件操作做出一定决策,以便于给用户带来更好的交互体验 ;
那么该如何实现判断用户所操作的事件呢?
所以,今天主要介绍的内容就是关于DOM的事件高级:
一、事件对象
二、事件流
三、事件委托
四、表格操作案例
文章目录
一、事件对象
回顾普通事件监听的基础语法结构,可以看到函数中并没有任何参数:
DOM对象.addEventlistener('事件', function (){})
而相对于存在 事件对象 的语法结构而言,可以看到函数中存在了 e
这个参数:
DOM对象.addEventlistener('事件', function (e){})
那么,可以思考的就是:事件对象是什么?如何获取?获取的对象有哪些常用的属性?分两小节展开:
1. 获取事件对象
- 事件对象: 也是个对象,这个对象里存在了事件触发时的相关信息,该对象只存在于事件当中;例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息;
- 获取方式: 在事件绑定的 回调函数 中,添加的第一个参数,就是事件对象,例如:
e
;
⭐注意:事件对象在开发过程中,一般命名为
event
、ev
、e
,其本质是形参,但并不是用来接受参数的,而是判断事件操作的相关信息的,返回为 PointerEvent
代码样例:
div.addEventListener('click',function(e){
console.log(e);
})
效果图示(在PointerEvent之下的所有内容都是该事件所具有的操作属性):
2. 事件对象常用属性
通过上述样例效果图示可看出,事件对象中通常包含很多属性,但是对于前端开发的过程中往往最常用的以下四类:
部分常用属性例举:
type
:获取当前的事件类型;pageX/pageY
:获取光标相对于整个HTML页面左上角的位置;offsetX/offsetY
:获取光标相对于当前DOM元素左上角的位置(只有在元素内部点击才有效);clientX/clientY
:获取光标相对于浏览器可见窗口左上角的位置;key
:用户按下的键盘键的值(暂不提倡使用keyCode);
⭐注意:用到按下键盘事件的常用事件是
keydown
或者keyup
,它们唯一的区别就是触发点不同;keydown
是选择在按下去的一瞬间实现事件触发;而keyup
则是在键盘弹起的一瞬间才会实现事件触发(往往这个兼容性会更好一些);
兼容性应用场景: 为了避免出现在提交输入内容之后,无法实现输入框清空效果,常常选用keyup
作为键盘按下事件;
二、事件流
一个项目中,某个事件在完整的执行过程中所流经的路径就是 事件流 ,事件流当中通常又会分为两个阶段:事件捕获 和 事件冒泡,不同的阶段可以处理不同的事务,但是对于不同的 父子级事件 处理而言,事件之间也会存在相互的影响,解决这种影响就需要运用到 阻止事件流动 的操作了,下面均会详细介绍:
1. 阶段说明
假设页面中含有一个div,当触发事件时,便会经历两个阶段,分别是 捕获阶段 和 冒泡阶段 ,如图所示:
简单来说:捕获阶段是从父到子;冒泡阶段是从子到父
2. 事件捕获
基础概念: 从DOM的根元素
开始去执行对应的事件( 从外到里 ),需要写对应代码才能看到效果;
基本语法结构:
DOM.addEventListener(事件类型, 事件处理函数, 是否使用捕获机制)
说明:
① addEventListener
第三个参数传入 true
代表的是捕获阶段触发(很少使用);
② 若传入 false
代表冒泡阶段触发,默认就是 false
;
③ 若是用 L0 事件监听,则只有冒泡阶段,没有捕获;
3. 事件冒泡
基础概念: 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡;
简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件;
说明:
① 事件冒泡是默认存在的;
② 同名的事件才会出现冒泡的情况;
4. 阻止事件流动
为什么要阻止事件流动?
原因:默认就有冒泡模式的存在,所以很容易导致事件影响到父级元素,但是若想把事件就限制在当前元素内,那么就需要 阻止事件流动 ;
方式一:
事件对象.stopPropagation()
说明:
① 此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效;
方式二:
鼠标经过事件:
mouseover
和mouseout
会有冒泡效果mouseenter
和mouseleave
没有冒泡效果(推荐)
说明:
① 此方法只能用于鼠标经过事件;
方式三:
事件对象.preventDefault()
说明:
① 阻止默认行为,比如链接点击不跳转,表单域的跳转
5. 两种注册事件下阻止事件流动的区别
① 传统 on
注册(L0):
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件) ;
- 直接使用
null
覆盖,就可以实现事件的解绑; - 都是冒泡阶段执行的;
② 事件监听注册(L2):
- 语法:
addEventListener(事件类型, 事件处理函数, 是否使用捕获)
; - 后面注册的事件不会覆盖前面注册的事件(同一个事件);
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行;
- 必须使用
removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
; - 匿名函数无法被解绑;
三、事件委托
基础概念:其也可称之为 事件代理(Event Delegation);是JavaScript中常用绑定事件的常用技巧。顾名思义,事件代理 就是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。事件代理 的原理是DOM元素的事件冒泡;
说明:
① 优点:给父级元素加事件(可以提高性能);
② 原理:事件委托其实是利用事件冒泡的特点;
③ 实现:事件对象.target
可以获得真正触发事件的元素;
⭐注意:
- 单个事件没有必要用事件委托;
- 多个事件也需要分析才能知道是否应该使用事件委托,具体什么时候能需要使用事件委托;
- 部分情况可直接替代了for循环的遍历需求;
四、表格操作案例
具体代码:
// 1. 准备好数据后端的数据
let arr = [
{ stuId: 1001, uname: '小柴爱程序', age: 23, gender: '男', salary: '20000', city: '杭州' },
]
// 获取父元素 tbody
let tbody = document.querySelector('tbody')
// 添加数据按钮
// 获取录入按钮
let add = document.querySelector('.add')
// 获取各个表单的元素
let uname = document.querySelector('.uname')
let age = document.querySelector('.age')
let gender = document.querySelector('.gender')
let salary = document.querySelector('.salary')
let city = document.querySelector('.city')
// 渲染函数 把数组里面的数据渲染到页面中
function render() {
// 先干掉以前的数据 让tbody 里面原来的tr 都没有
tbody.innerHTML = ''
// 在渲染新的数据
// 根据数据的条数来渲染增加 tr
for (let i = 0; i < arr.length; i++) {
// 1.创建tr
let tr = document.createElement('tr')
// 2.tr 里面放内容
tr.innerHTML = `
<td>${arr[i].stuId}</td>
<td>${arr[i].uname}</td>
<td>${arr[i].age}</td>
<td>${arr[i].gender}</td>
<td>${arr[i].salary}</td>
<td>${arr[i].city}</td>
<td>
<a href="javascript:" id="${i}">删除</a>
</td>
`
// 3.把tr追加给 tobdy 父元素.appendChild(子元素)
tbody.appendChild(tr)
}
}
// 页面加载就调用函数
render()
add.addEventListener('click', function () {
// alert(11)
// 获得表单里面的值 之后追加给 数组 arr 用 push方法
arr.push({
// 得到数组最后一条数据的学号 1003 + 1
stuId: arr[arr.length - 1].stuId + 1,
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
})
// console.log(arr)
// 重新渲染函数
render()
// 复原所有的表单数据
uname.value = age.value = salary.value = ''
gender.value = '男'
city.value = '北京'
})
// 删除操作, 删除的也是数组里面的数据 , 用事件委托
tbody.addEventListener('click', function (e) {
if (e.target.tagName === 'A') {
arr.splice(e.target.id, 1)
// 重新渲染函数
render()
}
})
具体效果图如下:
总结
今天是继续学习Web APIs的第四天,内容不多,但练习极为重要,今天所总结出来的所有知识,希望对大家有用,同时也希望这篇文章可以有一个好的展现量和得到更多人的支持,谢谢每一位浏览文章的人,要相信小柴码文,必是好文,欢迎各位 点赞+收藏+关注 啦! ! !
以上就是所要介绍的Web APIs基础学习的第四节内容,后续即将更新前端开发的学习目标。感谢关注和支持,让我们一起成长!
有兴趣可回顾一下JavaScript基础学习的文章内容,再结合之前所介绍的CSS基础学习以及HTML基础学习,大脑里的内容会更加丰富而充实的,毕竟综合性复习和学习是更会加深印象的哟!!!