目录
(4). 示例: 使用HTML DOM简化动态生成表格,并实现删除行
【前文回顾】👉 DOM操作之如何添加、删除、替换元素_04

一. HTML DOM常用对象: 对常用元素的简化操作
1. img元素: 唯一的简化,就是创建img时
(1). var img元素=new Image();
(2). 旧js中: var img元素=document.createElement("img");
(3).强调: 常用的DOM元素中,只有img元素能用new创建。其余元素都只能用document.createElement()创建。
2. table元素: 逐级管理的方式
(1). table管着行分组
a. table可以创建行分组
1). var thead=table.createTHead(); //相当于旧js两句话
旧js: var thead=document.createElement("thead");//即创建
table.appendChild(thead);//又添加
2). var tbody=table.createTBody(); //相当于旧js两句话
3). var tfoot=table.createTFoot(); //相当于旧js两句话
b. table可以删除行分组
1). table.deleteTHead();
2). table.deleteTFoot();
c. table可以获取行分组
1). table.tHead
2). table.tFoot
3). table.tBodies[i]
因为HTML标准中规定,其实一个table中可以有多个tbody。HTML DOM就将多个tbody集中保存在一个table.tBodies集合中。通过下标方式,访问某一个tBody。正是因为一个table下可以有多个tBody,所以table是没有deleteTBody()函数的,因为不知道该删除哪一个。
(2). 行分组管着行
a. 行分组可以添加行:
1). var tr=行分组.insertRow(i); //一个函数干2件事
2). 意为: 先创建一个新行对象,再将新行对象添加到行分组中i位置。
3). 大概相当于旧js中:
var tr=document.createElement("tr");
行分组.appendChild(tr);
4). 固定套路:
i. 在当前行分组末尾追加新行: var tr=行分组.insertRow()//默认结尾
ii. 在当前行分组开头插入新行: var tr=行分组.insertRow(0)
b. 行分组可以删除行:
1). 行分组.deleteRow(i)
2). 意为: 删除当前行分组内的第i行
3). 坑: 如果deleteRow.前使用行分组删除行时,则下标必须使用行在行分组内的相对下标位置!
4). 问题: 如果用户随便点击一行中的删除按钮,我们虽然可以根据按钮逐级向上找到父元素tr对象。但是,依然不知道用户点的这一行在整个行分组内是第几行。如果不知道下标,就无法删除当前行。
5). 解决: 其实每个行对象身上都自动就有一个属性rowIndex。记录着当前行对象在整个表中的下标位置。
6). 坑: 行对象的rowIndex属性记录的是行在整个表中的下标位置,不是在行分组内的相对位置。而受到表头行的影响,表体中的行的rowIndex值比行在行分组内的相对位置都要大!如果使用行分组作为主语,使用rowIndex作为删除行的参数值,结果实际删除的行一定是原本要删除行的下一行!

7). 解决: 今后要想删除任意一行,不要用行分组作为主语,而应该用table作为主语:
table.deleteRow(tr.rowIndex)
因为主语变成了table,所以参数值刚好也是行在整个table中的下标位置,参数与主语配套了!

c. 行分组可以获取行
行分组.rows[i] //行分组下的所有行对象都集中保存在名为rows的集合中
(3). 行管着格
a. 行可以添加格:
1). var 格对象=行.insertCell()//末尾插入!
插入 格
2). 意为: 先创建一个td对象,再将td对象追加到行中
b. 行可以删除格:
行.deleteCell(i) //删除行中下标为i的一个单元格
c. 行可以获取格:
行.cells[i] //行中的所有格对象已经被提前保存在了名为cells的集合中
(4). 示例: 使用HTML DOM简化动态生成表格,并实现删除行
1_createTable3_delete.html
<!DOCTYPE html>
<html>
<head>
<title>动态创建表格</title>
<meta charset="utf-8" />
<style>
table {
width: 600px;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="data">
<table>
<thead>
<tr>
<th>ename</th>
<th>salary</th>
<th>age</th>
<th></th>
</tr>
</thead>
</table>
</div>
<script>
var json = [
{ ename: "Tom", salary: 11000, age: 25 },
{ ename: "John", salary: 13000, age: 28 },
{ ename: "Mary", salary: 12000, age: 25 },
];
var table = document.querySelector("#data>table");
//创建tbody
var tbody = document.createElement("tbody");
//遍历json数组中每个员工对象
for (var emp of json) {
//每遍历一个员工对象,就要创建tr,添加到tbody下
//每次都在末尾追加新行
var tr = tbody.insertRow();
//遍历当前员工对象中每个属性
for (var key in emp) {
//每遍历一个属性,就创建一个td,添加到tr下
// var td=document.createElement("td");
// tr.appendChild(td);
var td = tr.insertCell();
//设置当前td的内容为当前员工对象emp的当前属性值
//对象底层的原理: js中对象底层其实也是一个关联数组
td.innerHTML = emp[key]; //对象[变量或表达式]
}
//除了遍历当前对象的每个属性添加的数据格之外,额外再多添加一个格
// var td=document.createElement("td");
// tr.appendChild(td);
var td = tr.insertCell();
//每个td中要再添加一个按钮
var btn = document.createElement("button");
btn.innerHTML = "×";
td.appendChild(btn);
//为每个删除按钮绑定单击事件
btn.onclick = function () {
//根据当前点的按钮逐级找到当期要删除的行
var tr =
this.parentElement.parentElement; //td //tr
//获取当前行中第一个td的内容
// var ename=tr.children[0].innerHTML;
var ename = tr.cells[0].innerHTML;
//先跟用户确认是否删除
var result = confirm(`是否继续删除 ${ename} 吗?`);
//只有用户点确定,确认继续删除时,才执行删除操作
if (result == true) {
//删除table中一行的标准做法
table.deleteRow(tr.rowIndex);
} //否则如果用户点取消,说明用于反悔了!就什么也不做!
};
}
//最后在查找table,将tbody一次性装入table中
//只需要一次重绘页面即可!
table.appendChild(tbody);
</script>
</body>
</html>
运行结果:
🌱 扩展:对象底层的原理:
◼️对象底层的原理: js中对象底层其实也是一个关联数组。——整个js内存中,一切都是关联数组!
👉1). 都是保存的"名值对儿"的集合
👉2). 其实无论访问数组的元素,还是访问对象的成员,都可以用["下标名"]方式访问。只不过,如果属性名是自定义字符串,就可简写为".属性名"方式
➡️ 如果我们写".属性名"会被自动翻译回["属性名"]
➡️ 总结: 今后,如果要访问的属性名是写死的固定不变的,既可以用[""],又可以用.
➡️ 但是, 今后,要访问的属性名来自于变量或动态拼接生成,不是固定的,只能用[变量或表达式],还不能加""
3. form元素
(1). 获取<form>时: document已经将网页中的所有<form>元素,都集中保存在了document.forms集合中,可通过下标方式访问网页中某一个<form>
document.forms[i]
(2). 还可以进一步简化获取<form>内的各种表单元素:
a. 标准: form对象已经将表单中所有的表单元素都集中保存在了名为elements的集合中。
var 一个表单元素=form对象.elements[i/name/id]
b. 更简写: 如果要找的表单元素有name属性,可以直接
form对象.name名
(3). 自动获得焦点: 表单元素.focus()
(4). 示例: 使用HTML DOM简写带样式的表单验证:
0_valiWithCss.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>实现带样式的表单验证</title>
<style>
table {
width: 700px;
}
td:first-child {
width: 60px;
}
td:nth-child(2) {
width: 200px;
}
/*IE*/
td:first-child + td {
width: 200px;
}
td span {
color: red;
}
.vali_info {
display: none;
}
.txt_focus {
border-top: 2px solid black;
border-left: 2px solid black;
}
.vali_success,
.vali_fail {
background-repeat: no-repeat;
background-position: left center;
display: block;
}
/*如果验证文本框中的内容通过,则修改文本框旁边的div的class为vali_success,文本框旁边的div就变成了验证通过的样式!*/
.vali_success {
background-image: url("images/ok.png");
padding-left: 20px;
width: 0px;
height: 20px;
overflow: hidden;
}
/*当验证文本框的内容没通过,则修改文本框旁边的div的class为vali_fail,就能让文本框旁边的div变成验证失败的样子*/
.vali_fail {
background-image: url("images/err.png");
border: 1px solid red;
background-color: #ddd;
color: Red;
padding-left: 30px;
}
</style>
</head>
<body>
<form id="form1">
<h2>增加管理员</h2>
<table>
<tr>
<td>姓名:</td>
<td>
<input name="username" />
<span>*</span>
</td>
<td>
<div class="vali_info">10个字符以内的字母、数字或下划线的组合</div>
</td>
</tr>
<tr>
<td>密码:</td>
<td>
<input type="password" name="pwd" />
<span>*</span>
</td>
<td>
<div class="vali_info">6位数字</div>
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
<input type="submit" value="保存" />
<input type="reset" value="重填" />
</td>
</tr>
</table>
</form>
<script>
//想获得网页中唯一的一个form
//旧DOM:
//var form=document.getElementById("form1");
//HTML DOM:
var form = document.forms[0];
console.log(form);
//DOM 4步
//1. 查找触发事件的元素
//本例中: 姓名、密码文本框失去焦点时触发验证
//用name属性分别找到两个文本框
// var inputName=document.getElementsByName("username")[0];//复习第一天查找元素
// var inputName=form.elements["username"];
var inputName = form.username;
var inputPwd = form.pwd;
//希望页面一加载,姓名或是密码文本框就自动获得焦点!
//如果希望实现点哪个文本框,哪个文本框就获得焦点,需要同时给2个文本框绑定获得焦点事件处理函数,请参看valiWithCSS.html
inputName.focus();
// inputPwd.focus();
//2. 绑定事件处理函数
//为两个文本框绑定失去焦点函数
//当姓名文本框失去焦点时,自动执行
inputName.onblur = function () {
//3. 查找要修改的元素
//本例中: 要修改当前文本框的爹的下一个兄弟的第一个孩子
var div = this.parentElement.nextElementSibling.children[0];
//4. 修改元素
//先定义验证姓名的正则表达式
var reg = /^\w{1,10}$/;
//如果用正则表达式验证当前姓名文本框的内容通过
if (reg.test(this.value) == true) {
//就修改div的class为验证通过的样式类名
div.className = "vali_success";
} else {
//否则如果验证不通过
//就修改div的class为验证不通过的样式类名
div.className = "vali_fail";
}
};
//当密码文本框失去焦点时,自动执行
inputPwd.onblur = function () {
//3. 查找要修改的元素
//本例中: 要修改当前文本框的爹的下一个兄弟的第一个孩
var Pdiv = this.parentElement.nextElementSibling.children[0];
//4. 修改元素
//先定义验证密码的正则表达式
var reg = /^\d{6}$/;
//如果用正则表达式验证当前密码文本框的内容通过
if (reg.test(this.value) == true) {
//就修改Pdiv的class为验证通过的样式类名
Pdiv.className = "vali_success";
} else {
//否则如果验证不通过
//就修改div的class为验证不通过的样式类名
Pdiv.className = "vali_fail";
}
};
</script>
</body>
</html>
运行结果:
⬛总结: DOM 5件事: 增删改查+事件绑定
1. 查找元素: 4种查找方式
2. 修改元素: 3种东西可修改
3. 添加/删除元素
4. HTML DOM常用对象:(了解即可)
(1). var img=new Image()
(2). table
a. table管着行分组:
1). 添加行分组:
var thead=table.createTHead()
var tbody=table.createTBody()
var tfoot=table.createTFoot()
2) 删除行分组:
table.deleteTHead(); table.deleteTFoot()
3). 获取行分组:
table.tHead table. tFoot table.tBodies[i]
b. 行分组管着行:
1). 添加行:
i. 任意行插入新行: var tr=行分组.insertRow(i);
ii. 开头插入新行: var tr=行分组.insertRow(0)
iii. 末尾追加新行: var tr=行分组.insertRow()
2). 删除行: table.deleteRow(tr.rowIndex)
3). 获取行: 行分组.rows[i]
c. 行管着格:
1). 添加格: var td=tr.insertCell()
2). 删除格: tr.deleteCell(i)
3). 获取格: tr.cells[i]
(3). form:
a. 获取form元素: document.forms[i]
b. 获取form中的表单元素:
1). 标准: form.elements[i或id或name名]
2). 简写: 如果有name属性: form.name名
c. 让表单元素自动获得焦点: 表单元素.focus()
【后文传送门】👉 深入浅出浏览器对象模型—BOM基础知识详解_06
如果这篇【文章】有帮助到你,希望可以给【青春木鱼】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【前端技术】感兴趣的小可爱,也欢迎关注❤️❤️❤️【青春木鱼】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!




5665





