一:简介
节点(复习):页面上的所有元素都可以当成是节点。
节点的作用:获取元素,我们的DOM提供了两种获取元素的方法,一种是通过一些方法来获取(例如我们之前用过的getElementById等),但是,这些方法非常繁琐,而且逻辑性也不强,只要用到就得一个一个都获取到。另一种方法就是用节点来获取,可以先获得一个节点,之后便可通过这个节点来获取它的兄弟或者父子。这样非常方便,逻辑性也强了些,就是兼容性差了点。
一般的,节点至少拥有:nodeType(节点类型),nodeName(节点名称),nodeValue(节点值)三个属性。元素节点nodeType为1,属性节点nodeType为2,文本节点(包括文字,空格,换行)nodeType为3,但一般情况下,我们操作的都是元素节点。
重点掌握:创建,添加,删,查,改,属性操作,事件操作。
二:节点操作-父节点
node.parentNode:得到的是离node最近的一个父节点,找不到的话返回为空。
三:节点操作-子节点
parent.childNodes:得到的是parent里所有的子节点(包含元素和文本节点),所以想要获取里面的的元素节点,还需要专门的处理,所以不太常用。
parent.childrenp(非标准),但是,很方便,很常用。
parentNode.firstChild(也包括文本节点):获取的是元素的第一个子节点。
parentNode.lastChild(也包括文本节点):获取的是元素的最后一个子节点。
parentNode.firstElementChild:获取的是元素的第一个子元素。(IE9)
parentNode.lastElementChild:获取的是元素的最后一个子元素。(IE9)
parentNode.children[num];num为0,第一个子元素,num为num.length,最后一个子元素。
四:节点操作-小案例-下拉菜单
例子:
<!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:返回元素的下一个节点,找不到就返回为空,返回所有节点
node.previousSibling:返回元素上一个节点,找不到返回null,返回所有节点。
node.nextElementSibling:下一个兄弟元素节点。(IE9)
node.previousElementSibling:上一个兄弟元素节点。(IE9)
六:节点操作-创建添加节点
document.creatElement('tagName'):这个方法创建创建指定tagName的元素,这个元素本来是不存在的,是跟据需求动态生成的,所以这个元素也叫做动态创建元素节点。
parentNode.apppendChild(child):用这种方法将一个元素添加到指定父节点的子节点列表的末尾,类似于CSS中的after伪元素。在列表末尾添加元素,相当于数组的push()。
parentNode.insertBefore(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>),文档流执行完会导致页面重绘,那么除了这个div其余元素都将不会被留下。
- element.innerHTML->创建元素的效率较3低,但是如果用数组封装拼接之后,效率将会大大提高,超过3.
- element.creatElement->结构更加清晰,但是效率低于2的封装方法。