【Web前端笔记-基础】第十六课,节点操作(DOM核心)
一:简介
在网页结构中,默认每个元素都可被视为节点。
获取元素的方式有两种途径:一种是通过一些特定的方法(如之前使用的getElementById)直接获取;另一种则是利用节点属性来进行间接获取。
通过节点操作的优势在于能够方便地访问兄弟或父级元素,并且其逻辑体系相对清晰;然而这种做法在跨浏览器兼容性方面存在一定的局限性。
每个节点都具备基本属性:
- nodeType:区分不同类型的节点(1为元素节点、2为属性节点、3为文本节点);
- nodeName:表示当前节点对应的名称;
- nodeValue:存储与该节点相关联的内容;
通常情况下我们主要处理的是元素类型的node。
建议重点掌握以下操作:
创建新节点
向文档中添加现有节点
删除现有或新增的文档中的所有或部分内容
查询指定类型或值的特定信息
修改现有信息的基本参数
触发或终止事件流程
二:节点操作-父节点
通过访问该元素的parent属性来获取。该元素将返回其直接父节点;如果找不到,则返回空值。
三:节点操作-子节点
主要返回所有子节点(即包含所有直接嵌套在父节点中的标签)。然而,在这种情况下想要单独获得其中的那些包含具体类型内容的标签则需要额外的操作步骤因此并不常用。
虽然不是标准方法但确实非常方便而且被广泛使用。
通过访问父节点的第一个孩子节点可以找到第一个可选属性值。
同样地通过访问父节点的最后一孩子节也可以找到最后可选属性值。
为了找到第一个可选属性值可以通过ParentNode.firstElementChild方法来实现。(仅适用于IE9及以上版本)
为了找到最后可选属性值可以通过ParentNode.lastElementChild方法来实现。(仅适用于IE9及以上版本)
通过使用索引访问的方法比如ParentNode.children[num]其中num为0时会得到第一个可选属性值而当num等于数组长度时则会得到最后一个可选属性值这种用法非常普遍并且简单易行
四:节点操作-小案例-下拉菜单
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>下拉菜单练习</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
.nav{
width: 523px;
margin: 100px auto;
}
.nav>ul{
list-style: none;
border-top: 1px solid #fecc5b;
}
.nav>ul>li{
float: left;
display: block;
width: 130px;
height: 30px;
position: relative;
/* background-color: rgb(244, 236, 248); */
}
.nav>ul>li>ul{
list-style: none;
position: absolute;
top: 30px;
}
a{
color: black;
text-decoration: none;
display: block;
width: 130px;
height: 30px;
text-align: center;
line-height: 30px;
}
a:hover{
display: block;
width: 130px;
height: 30px;
text-align: center;
line-height: 30px;
background-color: rgb(243, 236, 248);
color:#fecc5b ;
}
.nav>ul>li>ul{
display: none;
}
</style>
</head>
<body>
<div class="nav">
<ul class="fail">
<li>
<a href="#">菜单</a>
<ul>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
</ul>
</li>
<li>
<a href="#">菜单</a>
<ul>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
</ul>
</li>
<li>
<a href="#">菜单</a>
<ul>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
</ul>
</li>
<li>
<a href="#">菜单</a>
<ul>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
<li><a href="#">下拉菜单</a></li>
</ul>
</li>
</ul>
</div>
<script type="text/javascript">
var fail=document.querySelector(".fail");
var lis=fail.children;
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover=function(){
this.children[1].style.display="block";
}
lis[i].onmouseout=function(){
this.children[1].style.display="none";
}
}
</script>
</body>
</html>
效果:

五:节点操作-兄弟节点
node.nextSibling:通过此属性可以获取当前元素的下一个子节点;若无则为null;并包含当前元素的所有子节点。
node.previousSibling:通过此属性可以获取当前元素的前一个子节点;若无则为null;并包含当前元素的所有前驱子节点。
node.nextElementSibling:此属性用于获取与当前对象同级别的直接后跟兄弟元结。(IE9)
node.previousElementSibling:此属性用于获取与当前对象同级别的直接前置兄弟元结。(IE9)
六:节点操作-创建添加节点
document.generateElement('tagName'):该方法用于生成指定tagName的元素节点。
parentNode.insertChildToEnd(child):此方法将一个元素插入到父节点子节点列表的末尾位置。
parentNode.insertBefore(child, specifiedElement):该操作将指定child元素插入到指定的位置之前。
七:节点操作-小案例-简单留言板发布
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>简单版发布留言</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
div{
width: 300px;
margin: 100px auto;
}
ul li{
/* padding-top: 20px; */
margin-top: 20px;
background-color: pink;
color: red;
width: 160px;
}
li a{
float: right;
color: black;
text-decoration: none;
}
li a:hover{
text-decoration: underline;
}
</style>
</head>
<body>
<div class="">
<textarea rows="10" cols="20"></textarea>
<br />
<button>发布</button>
<ul>
</ul>
</div>
<script type="text/javascript">
//1.获取元素
var btn=document.querySelector("button");
var text=document.querySelector("textarea");
var ul=document.querySelector("ul");
//注册事件,处理程序
btn.onclick=function(){
if(text.value==""){
alert("请输入!");
return false;
}else{
//1.创建元素
var li=document.createElement("li");
li.innerHTML=text.value+"<a href='javascript:;'>删除</a>";
//2.添加元素
// ul.appendChild(li);//从上往下排
ul.insertBefore(li, ul.children[0]);//从上往下排,最新的留言放在最前面
//获取元素-链接
var deletes=document.querySelectorAll("a");
for (var i=0;i<deletes.length;i++) {
deletes[i].onclick=function(){
//删除当前a的父亲li
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
效果:

八:节点操作-删除节点
parentNode.removeChild(child):删除相应子节点。
九:节点操作-小案例-留言板的删除
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>简单版发布留言</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
div{
width: 300px;
margin: 100px auto;
}
ul li{
/* padding-top: 20px; */
margin-top: 20px;
background-color: pink;
color: red;
width: 160px;
}
li a{
float: right;
color: black;
text-decoration: none;
}
li a:hover{
text-decoration: underline;
}
</style>
</head>
<body>
<div class="">
<textarea rows="10" cols="20"></textarea>
<br />
<button>发布</button>
<ul>
</ul>
</div>
<script type="text/javascript">
//1.获取元素
var btn=document.querySelector("button");
var text=document.querySelector("textarea");
var ul=document.querySelector("ul");
//注册事件,处理程序
btn.onclick=function(){
if(text.value==""){
alert("请输入!");
return false;
}else{
//1.创建元素
var li=document.createElement("li");
li.innerHTML=text.value+"<a href='javascript:;'>删除</a>";
//2.添加元素
// ul.appendChild(li);//从上往下排
ul.insertBefore(li, ul.children[0]);//从上往下排,最新的留言放在最前面
//获取元素-链接
var deletes=document.querySelectorAll("a");
for (var i=0;i<deletes.length;i++) {
deletes[i].onclick=function(){
//删除当前a的父亲li
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
效果:

十:节点操作-复制节点
node.cloneNode:该方法用于生成调用该方法的节点的一个副本,并被称为克隆或拷贝节点。
当括号内的参数为空或设置为false时,则生成浅拷贝(仅复制元标签而不复制内部数据)。
而当括号内的参数设置为true时,则生成深拷贝(不仅包括元标签还包括内部数据)。
十一:节点操作-小案例-动态生成表格
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>动态生成表格</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
table{
width: 500px;
margin: 100px auto;
border-collapse: collapse;//设置表格的边框是否被合并成一个单一的边框
}
td,th{
border: 1px solid #333;
text-align: center;
}
thead tr{
height: 40px;
background-color: #ccc;
}
a{
color: black;
text-decoration: none;
}
a:hover{
color: #f00;
text-decoration: underline;
}
</style>
</head>
<body>
<div class="creat_Tab">
<table border="" cellspacing="1" cellpadding="">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<script type="text/javascript">
//学生数据
var datas=[{
name: "魏璎珞",
subject:"JavaScript",
score:100,
},
{
name: "弘历",
subject:"JavaScript",
score:98 ,
},
{
name: "傅恒",
subject:"JavaScript",
score:99,
},
{
name: "明玉",
subject:"JavaScript",
score:89,
},
{
name: "猪蹄子",
subject:"JavaScript",
score:0,
}]
//创建行,通过循环
var tbody=document.querySelector('tbody');
for (var i = 0; i < datas.length; i++) {
// 创建tr行
var tr=document.createElement("tr");
tbody.appendChild(tr)
//创建单元格
for (var k in datas[i]) {
//创建单元格
var td=document.createElement('td');
//赋值
td.innerHTML=datas[i][k];
tr.appendChild(td);
}
//创建删除单元格及标签
var td=document.createElement("td");
td.innerHTML='<a href="javascript:;">删除</a>';
tr.appendChild(td);
//添加删除操作:点击删除,所在行delete
}
//获取事件源
var alink=document.querySelectorAll('a');
for (var i = 0; i < alink.length; i++) {
alink[i].onclick=function(){
//这里注意a的父亲是单元格,a的爷爷才是tr行,找删除元素时。一定要看仔细
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
</html>
效果:

十二:三种动态创建元素的区别
- document.write()->冷门:例如,在调用
document.write(<div>123</div>)后, 文档流会完成处理并导致页面刷新, 因此其他所有元素将不再保留。
- element.innerHTML->创建元素的效率较3低, 如果采用数组封装的方式拼接元素则效率将会显著提升至4级。
- element.creatElement->在使用
element.creatElement时, 其优势在于逻辑结构更加清晰; 然而其操作速度仅相当于其他高效封装方法(如2级)的一半。
