之前要想获取元素,得先获取父亲再获取你想要的,逻辑性不强而且繁琐(利用dom提供的方法来获取)
利用节点层级关系来获取更方便,逻辑性强但是兼容性差
一、节点之间的层级
1.父节点操作
<div class="box">
<div class="code"></div>
</div>
<script>
var code=document.querySelector('.code');
// var box=document.querySelector('.box');//以前的做法
code.parentNode;//现在的新做法,直接获取父亲节点
</script>
parentNode得到的是离它最近的父亲,如果它还有爷爷的话,得到的也是父亲,如果找不到返回null
2.子节点操作
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var ul=document.querySelector('ul');
// var lis=document.querySelectorAll('li');//以前的做法
ul.childNodes;
</script>
1.第一种做法比较麻烦,console.log之后它打印出来的不光是li,还有里面的文本元素(空格换行之类的),你要是想只要元素还得去遍历获取。
2.parentNode.children(非标准,但是兼容)用的多
console.log(ul.children);
3.获取第一个子元素和最后一个子元素
1.获取第一个子元素:parentNode.firstChild
获取最后一个子元素:parentNode.lastChild
跟childNodes一样,包括空格换行啥的,不好用
2.获取第一个子元素:parentNode.firstElementChild
获取最后一个子元素:parentNode.lastElementChild
(但是只有ie9以上才支持)
3.非常好用的办法!
获取第一个子元素:parentNode.children[0];
获取最后一个子元素:parentNode.children[parentNode.children.length-1];
案例:下拉菜单
<style>
.nav{
margin: 100px 200px;
text-align: center;
}
li{
list-style: none;
}
a {
color: #666;
text-decoration: none;
/*超链接去掉下划线并变色*/
text-align: center;
}
.box{
float: left;
/* margin-right: 20px; */
width: 100px;
}
ul{
padding: 0;
}
.box ul li{
border: 1px solid rgb(255, 166, 0);
border-top: 0;
}
.box ul{
display: none;
}
</style>
<body>
<div class="nav">
<li class="box">
<a href="">微博</a>
<ul>
<li><a href="">私信</a> </li>
<li><a href="">评论</a> </li>
<li><a href="">@我</a></li>
</ul>
</li>
<li class="box">
<a href="">微博</a>
<ul>
<li><a href="">私信</a> </li>
<li><a href="">评论</a> </li>
<li><a href="">@我</a></li>
</ul>
</li>
<li class="box">
<a href="">微博</a>
<ul>
<li><a href="">私信</a> </li>
<li><a href="">评论</a> </li>
<li><a href="">@我</a></li>
</ul>
</li>
<li class="box">
<a href="">微博</a>
<ul>
<li><a href="">私信</a> </li>
<li><a href="">评论</a> </li>
<li><a href="">@我</a></li>
</ul>
</li>
</div>
<script>
var boxs=document.querySelectorAll('.box');
//console.log(boxs[0].children[0]);
for(var i=0;i<boxs.length;i++)
{
boxs[i].onmouseover=function(){
this.children[1].style.display='block';
}
boxs[i].onmouseout=function(){
this.children[1].style.display='';
}
}
</script>
(图上没有显示鼠标)
还是比较简单的,就是我在设置函数的时候我设置的是点击boxs的第一个孩子a微博,然后下面那个用this就不太行了,因为a和ul是兄弟的关系,我之前的经验是看他点击了哪个,不要给他的父元素去设置,但是还没学兄弟有点不太行,还好给做出来了。
4.获取兄弟节点
1.带空格和换行,没什么大用
2.有兼容性问题
3.好用!但是实际上用兄弟用的不多
二、节点的增删
1.创建并添加元素节点(发表新的评论)
(1)父元素.appendChild(要添加的元素)
<body>
<ul></ul>
<script>
//给body里面没有的创建一个并获取这个元素
var li=document.createElement('li');
var ul=document.querySelector('ul');
ul.appendChild(li);
</script>
</body>
类似于数组的push,将子元素放到父元素的末尾
(2)父元素.insertBefore(要添加的元素节点,添加到谁前面)
<ul>
<li class="hh">123</li>
</ul>
<script>
//给body里面没有的创建一个并获取这个元素
var li=document.createElement('li');
var ul=document.querySelector('ul');
var hh=document.querySelector('.hh');
//ul.appendChild(li);//到父元素最后一位
ul.insertBefore(li,hh);
//ul.insertBefore(li,ul.children[0]);
</script>
案例:简单添加留言
核心思路:点击按钮之后,就创建一个li,然后添加到ul中去,同时还是把文本域的文字innerH TML给li
<style>
li{
list-style: none;
background-color: pink;
width: 500px;
margin-bottom: 10px;
}
a {
color: #666;
text-decoration: none;
/*超链接去掉下划线并变色*/
text-align: center;
}
</style>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>提交</button>
<ul>
<li>123</li>
</ul>
<script>
//给body里面没有的创建一个并获取这个元素
var content=document.querySelector('textarea');
var ul=document.querySelector('ul');
var button=document.querySelector('button');
button.onclick=function(){
if(content.value=='')
{
alert('您没有输入任何东西');
}
else{
var li=document.createElement('li');
ul.appendChild(li);//到父元素最后一位
li.innerHTML=content.value;
}
}
</script>
这里边注意textarea里面的内容是value
2.删除元素节点
(1)使用父元素.removeChild(子元素)
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul=document.querySelector('ul');
ul.removeChild(ul.children[0]);
</script>
</body>
(2)添加留言和删除留言
这次的删除按钮是在每条留言的后面,也就是和li在一个盒子里,在li.innerHTML=content.value还得加上一个链接a,但是a里面放#也不合适,那就是另一个页面了,阻止链接跳转是javascript:void(0);或者javascript:;
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button class="tijiao">提交</button>
<ul>
<!-- <li>123</li> -->
</ul>
<script>
//给body里面没有的创建一个并获取这个元素
var content=document.querySelector('textarea');
var ul=document.querySelector('ul');
var tijiao=document.querySelector('.tijiao');
tijiao.onclick=function(){
if(content.value=='')
{
alert('您没有输入任何东西');
}
else{
var li=document.createElement('li');
ul.insertBefore(li,ul.children[0]);//到父元素最后一位
li.innerHTML=content.value+"<a href='javascript:;'>删除</a>";
var as=document.querySelectorAll('a');
for(var i=0;i<as.length;i++)
{
as[i].onclick=function(){
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
我有点纳闷为啥后面的点击删除事件还有获取a、for循环啥的要写在else里面呢?
因为如果放在外面的话,没有执行点击提交按钮的时候就有var as生成了,那那个时候的as就是空的,后来的a标签虽然生成了,但是as获取的时候的a是以前空的a,所以不行。
3.复制元素节点
(1)node.cloneNode()
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ul=document.querySelector('ul');
var li1=ul.children[0].cloneNode();
ul.appendChild(li1);
查看元素发现里面没有数字1是为啥呢,看下面
(2)浅拷贝和深拷贝
node.cloneNode()括号里默认是false,也就是浅拷贝,只copy元素不copy内容
node.cloneNode(true),如果括号里是true就是深拷贝,copy元素和内容
三、动态生成表格
css和学生数据datas部分
li{
list-style: none;
background-color: pink;
width: 500px;
margin-bottom: 10px;
}
a {
color: #666;
text-decoration: none;
/*超链接去掉下划线并变色*/
}
table {
width: 400px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
}
th,
td {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
tbody tr {
height: 30px;
}
</style>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
var datas=[
{
names:'a',
subject:'javescript',
score:100
},
{
names:'b',
subject:'javescript',
score:10
},
{
names:'c',
subject:'javescript',
score:80
},
{
names:'d',
subject:'javescript',
score:78
},
]
</script>
创建行和单元格:有多少人就创建多少行,循环来做
var tbody=document.querySelector('tbody');
for(var i=0;i<datas.length;i++){
//var td=document.querySelector('tbody').createElement('td');这样写不对
var tr=document.createElement('tr');
tbody.appendChild(tr);
for(var k in datas[i])//k是个属性,obj(data[i])是对象,是数组中的每个对象
{
var td=document.createElement('td');
tr.appendChild(td);
}//最后的那个操作先不管
}
把对象里面的属性值(obj[k])给td,(k是属性名)
for(var k in datas[i])//k是个属性,obj(data[i])是对象,是数组中的每个对象
{
var td=document.createElement('td');
td.innerHTML=datas[i][k];
tr.appendChild(td);
}//最后的那个操作先不管
这里的datas[i][k]后面就不需要value,因为datas[i][k]就是那个值了,不像textarea它是那个框,得value才是里面的值呢
添加删除操作
这会也不用担心添加第四个会不会下面的乱跑了,因为第一个for循环控制第几行的,这样在第二个for循环外面(第一个for里面)创建一个create删除就行
var td=document.createElement('td');
td.innerHTML='<a href="javascript:;">删除</a>'
tr.appendChild(td);
让删除键起作用
因为整个第一个for都是在创建表格,现在创建完了就该把删除的代码写在第一个for下面了
var as=document.querySelectorAll('a');
for(var i=0;i<as.length;i++)
{
as[i].onclick=function(){
tbody.removeChild(this.parentNode.parentNode);
}
}
找了半天错,结果是在removeChild后面加了=