说到DOM,就能想到事件,那事件应用场景是什么呢?
一定是新增元素的处理了
想要实现新增元素,必须要了解什么是事件委托和事件冒泡
1.事件冒泡 : 当触发子元素的事件的时候, 所有的父级元素‘同名事件’都会被依次触发
元素->父元素->body->html->document->window
提起事件冒泡,还有一个与之相反的事件,叫做事件捕捉.事件捕捉是以前网景公司的产物,在当时发生了一件离奇的事情,比比尔盖茨为首的微软公司,当时在编程方面有一个最大的对头叫做网景公司,各自占据半壁江山,他们各自对标对方的产品,在微软推出了事件冒泡后,网景随之推出事件捕捉,这种不考虑实际用法的创造就必然会导致公司的下场就不会很好,事件捕捉的用法与事件冒泡截然相反,一个是触发子元素,所有父级元素会依次触发,则事件捕捉则是触发子元素的事件的时候,会从最顶级的父元素一级一级往里触发
元素->父元素->body->html->document->window
网景后来的结果大家可想而知.
2.事件委托 : 给父元素注册,委托子元素处理
事件委托原理 : 事件冒泡
事件委托应用场景 :
(1)实际开发最多: 给动态新增的子元素注册事件
(2)性能优化 : 如果所有的子元素都需要注册同名事件,只需要给父元素注册
事件委托注意点 :
(1)事件委托不能通过this找到子元素。 (this指向父元素)
(2)事件委托需要通过什么属性找到子元素: e.target
直接上图,完成如图案例,DOM知识点就能了解80%
不需要操作样式完成
表单内上移,下移与删除都需要实现相应的功能
下图为答案
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: #721c24;
}
h1 {
text-align: center;
color: #333;
margin: 20px 0;
}
table {
margin: 0 auto;
width: 800px;
border-collapse: collapse;
color: #004085;
}
th {
padding: 10px;
background: #cfe5ff;
font-size: 20px;
font-weight: 400;
}
td,
th {
border: 1px solid #b8daff;
}
td {
padding: 10px;
color: #666;
text-align: center;
font-size: 16px;
}
tbody tr {
background: #fff;
}
tbody tr:hover {
background: #e1ecf8;
}
.info {
width: 900px;
margin: 50px auto;
text-align: center;
}
.info input {
width: 80px;
height: 25px;
outline: none;
border-radius: 5px;
border: 1px solid #b8daff;
padding-left: 5px;
}
.info button {
width: 60px;
height: 25px;
background-color: #004085;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
border-radius: 5px;
}
.info .age {
width: 50px;
}
</style>
</head>
<body>
<h1>前端一览表</h1>
<form action="">
<div class="info">
姓名:<input type="text" class="uname" /> 年龄:<input type="text" class="age" />
性别:
<select name="gender" id="" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:<input type="text" class="salary" /> 就业城市:<select name="city" id="" class="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</div>
</form>
<h1>人员榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- <tr>
<td>1001</td>
<td>欧阳霸天</td>
<td>19</td>
<td>男</td>
<td>15000</td>
<td>上海</td>
<td>
<a href="javascript:" class="delete">删除</a>
</td>
</tr> -->
</tbody>
<script>
/* 思路分析
1.点击录入 :(注意点form表单中的按钮需要阻止默认事件)
1.1 非空判断 : 姓名、年龄、薪资不能为空
1.2 新增tr元素
* (1)创建tr (2)设置内容 (3)添加到table>tbody
1.3 清空form表单
2.点击删除 : 使用事件委托技术
2.1 点击删除, 删除tr标签 ( 删除按钮的父元素的td, td的父元素是tr)
3.上移
4.下移
*/
//1.获取元素
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')
let add = document.querySelector('.add')
let i = 100
//2.1 点击录入
add.onclick = function (e) {
/* 注意点:form表单元素中的按钮需要阻止默认条件 */
e.preventDefault()
//3.1 非空判断 : 姓名、年龄、薪资不能为空
if (uname.value.trim() == '' || age.value.trim() == '' || salary.value.trim() == '') {
alert('输入框不能为空')
} else {
//3.2 新增元素
//(1)创建空tr标签
let tr = document.createElement('tr')
//(2)设置内容
tr.innerHTML = `
<td>${i++}</td>
<td>${ uname.value }</td>
<td>${ age.value }</td>
<td>${ gender.value }</td>
<td>${ salary.value }</td>
<td>${ city.value }</td>
<td>
<a href="javascript:" class="up">上移</a>
<a href="javascript:" class="down">下移</a>
<a href="javascript:" class="delete">删除</a>
</td>
`
//(3)添加到tbody
document.querySelector('tbody').appendChild(tr)
}
//3.3 表单清空 form.reset()
document.querySelector('form').reset()
}
//2.2 使用事件委托给删除按钮注册点击事件
/*
事件委托 : 给父元素注册事件,委托子元素处理
事件委托注意点:
(1)不能使用this : 父元素
(2)使用e.target : 真正点击的子元素
(3)委托的父元素也不能是动态新增的
*/
document.querySelector('tbody').onclick = function (e) {
//点击tbody任意区域都会触发点击事件, 真正委托的是删除按钮
/*
this : tbody
e.target : 点击的子元素
e.target.parentNode.parentNode : tr
*/
//1.判断点击的是不是删除按钮
/*
(1) e.target.className == 'delete'
(2) e.target.classList.contains('delete')
true : 有这个类名 false:没有
*/
let tr = e.target.parentNode.parentNode
if (e.target.classList.contains('delete')) {
this.removeChild(tr)
} else if (e.target.classList.contains('up')) {
//判断tr是不是第一个儿子
if (tr.previousElementSibling) { //有哥哥可以上移
//上移:移到tr哥哥的前面
this.insertBefore(tr, tr.previousElementSibling)
} else {
alert('已经是第一个了')
}
} else if (e.target.classList.contains('down')) {
//判断tr是不是最后一个儿子
if (tr.nextElementSibling) {
//下移: 移到 弟弟的弟弟的前面
this.insertBefore(tr, tr.nextElementSibling.nextElementSibling)
} else {
alert('已经是最后一个了')
}
}
}
</script>
</table>
</body>
</html>