操作DOM节点,节点,可以利用节点层级关系(父子)来获取元素。节点有3个属性,分别是节点类型、节点名、节点值。元素节点类型值是1;属性节点类型值是2;文本节点类型值(文字、空格、换行)类型是3;实际开发中,节点操作主要是操作元素节点。节点的层级可以看作是父子兄的关系,白龙网指出。
1、节点类型
(1)父节点 .parentNode
<body>
<div class="box">
<span>子节点</span>
</div>
<script>
var span = document.querySelector('span');
//返回的是最近的父节点,如果没有父节点,则返回结果为空
console.log(span.parentNode);
</script>
</body>
(2)子节点 childNodes children
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var ul = document.querySelector('ul');
//1.childNodes,标准,返回值得是一个集合,包含元素节点、文本节点等内容,如果要使用该方法,需要判断元素的类型值1来筛选出元素
console.log(ul.childNodes);
for (i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType == 1) {
console.log(ul.childNodes[i]);
}
}
//2.children,非标准,返回值是元素节点,常用
console.log(ul.children);
</script>
</body>
(3)首尾元素
获取首尾元素,有3种方法,各有特点,区别对待,区别使用。
<body>
<ul>
<li>子元素太多了1</li>
<li>子元素太多了1</li>
<li>子元素太多了1</li>
<li>子元素太多了1</li>
<li>子元素太多了1</li>
</ul>
<script>
var ul = document.querySelector('ul');
//1.firstChild lastChild 获取的元素节点、文本节点
console.log(ul.firstChild);
console.log(ul.lastChild);
//2.firstElementChild lastElementChild 可以获取第一个与最后一个元素,但是要求IE9以上浏览器才能支持,即,存在兼容性问题
console.log(ul.firstElementChild);
console.log(ul.lastElementChild);
//3.实际开发中,一般会用这种方法来获取第一个、最后一个子元素
console.log(ul.children[0]);
console.log(ul.children[ul.children.length -1]);
</script>
</body>
案例1:新浪下拉菜单 鼠标经过下拉出现,鼠标离开,下拉显示
<body>
<style>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
}
.nav > li {
float: left;
}
.nav li ul {
display: none;
}
</style>
<ul class="nav">
<li>
<a href="#">白龙网</a>
<ul>
<li>前端技术</li>
<li>后端开发</li>
<li>SEO服务</li>
<li>小程序</li>
</ul>
</li>
<li>
<a href="#">白龙网</a>
<ul>
<li>前端技术</li>
<li>后端开发</li>
<li>SEO服务</li>
<li>小程序</li>
</ul>
</li>
<li>
<a href="#">白龙网</a>
<ul>
<li>前端技术</li>
<li>后端开发</li>
<li>SEO服务</li>
<li>小程序</li>
</ul>
</li>
<li>
<a href="#">白龙网</a>
<ul>
<li>前端技术</li>
<li>后端开发</li>
<li>SEO服务</li>
<li>小程序</li>
</ul>
</li>
</ul>
<script>
var ul = document.querySelector('.nav');
var lis = ul.children;
console.log(ul.children);
for (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>
(4)兄弟节点 nextSibling previousSibling nextElementSibling previousElementSibling
<body>
<div>白龙网</div>
<span>从建站到SEO的在线服务平台</span>
<p>最后一个段落</p>
<script>
var divs = document.querySelector('div');
//1.获取上一个/下一个兄弟节点,包括元素、文本,没有则返回空;如果只想获取元素,不想出现文本,使用nodeType判断即可
if (divs.nextSibling.nodeType === 1) {
console.log(divs.nextSibling);
}
console.log(divs.previousSibling);
//2.获取下一个、上一个元素节点,没有则返回空,存在兼容性问题
console.log(divs.nextElementSibling);
console.log(divs.previousElementSibling);
</script>
</body>
2、创建节点
自定义节点,需要两步才能完成,首先要创建节点,然后要添加节点。节点可以添加到后面,也可以添加到前面。
<body>
<ul>
<li>原有节点</li>
</ul>
<script>
//1.创建元素
var li = document.createElement('li');
var ul = document.querySelector('ul');
//2.添加元素,因为是从后面添加的元素,所以也叫追加元素
ul.appendChild(li);
var div = document.createElement('div');
//如果想要在已有子元素前面添加元素,则使用insertBefore(添加的元素,添加的元素位置)
ul.insertBefore(div,ul.children[0]);
</script>
</body>
案例1:简单的发布留言案例
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul>1</ul>
<script>
//获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
//添加事件
btn.onclick = function() {
//创建节点
var li = document.createElement('li');
if (text.value == '') {
alert('请输入内容:');
return false;
} else {
//输入内容显示到新建的LI中,实际上就是把文本域的值赋值给LI
li.innerHTML = text.value;
}
//添加节点
// ul.appendChild(li);
ul.insertBefore(li,ul.children[0]);
}
</script>
</body>
3、删除节点
删除节点,一定是删除父元素的子节点。
<body>
<button>删除</button>
<ul>
<li>白龙网</li>
<li>drupal开发</li>
<li>SEO优化</li>
</ul>
<script>
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
btn.onclick = function() {
if (ul.children.length == 0) {
//子节点删除完毕,按钮显示灰色状态,即:不可再删
btn.disabled = true;
} else {
//删除子节点:element.removeChild(child)
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
案例1:简单版在线留言内容的删除
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
<script>
//获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
//添加事件
btn.onclick = function() {
//创建节点
var li = document.createElement('li');
if (text.value == '') {
alert('请输入内容:');
return false;
} else {
//输入内容显示到新建的LI中,实际上就是把文本域的值赋值给LI,需要注意的是,此处要阻止a链接进行跳转,可以使用javascript:;或者javascript:void(0);另外,引自,又给出了一种添加节点的方法,即:加号拼接一个节点出现,或者用createElement()创建一个节点也可以
li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
//添加节点
ul.insertBefore(li,ul.children[0]);
//删除节点
var as = document.querySelectorAll('a');
for (i = 0 ; i < as.length; i++) {
//删除节点的时候,是删除所有链接节点的父亲,ul的儿子,即li,因此需要对数组as[i]添加事件,使用removeChild()删除每个li即可
as[i].onclick = function() {
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
4、复制节点 .cloneNode()
复制节点,也是克隆节点,使用方法类似于创建节点,要先复制再追加,复制才能成功。
<body>
<ul>
<li>白龙网</li>
<li>SEO教程</li>
<li>drupal</li>
</ul>
<script>
var ul = document.querySelector('ul');
//1.复制节点,如果.cloneNode()为空,或者false,称为浅拷贝,则只复制节点,不复制标签里面的内容;如果.cloneNode()为true,则既复制节点,又复制标签里面的内容;
var lili = ul.children[0].cloneNode();
var lili2 = ul.children[0].cloneNode(true);
//2.添加节点
ul.appendChild(lili);
ul.appendChild(lili2);
</script>
</body>
案例1:动态生成表格,并删除对应的行
用JS操作表格,添加行与单元格,并从数组中获取数据,这个案例类似于网站后台删除文章的功能。
<body>
<table border="1" cellspacing="0">
<thead>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</thead>
<tbody>
</tbody>
</table>
<script>
//准备数据
var datas = [
{
name: '周润发',
subject: 'Javascript',
score: '99'
},
{
name: '张学友',
subject: 'Javascript',
score: '90'
},
{
name: '刘德华',
subject: 'Javascript',
score: '80'
},
{
name: '刘德华',
subject: 'Javascript',
score: '80'
},
{
name: '刘德华',
subject: 'Javascript',
score: '80'
}
];
//2.创建行
var tbody = document.querySelector('tbody');
for (i = 0 ; i < datas.length; i++) {
var tr = document.createElement('tr');
tbody.append(tr);
//3.创建单元格
for (k in datas[i]) {
var td = document.createElement('td');
//4.填充数据:拿到对象的数据,并赋值给单元格
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
//添加删除单元格并给单元格添加数据
var td = document.createElement('td');
td.innerHTML = '<a href="javascript:;">删除</a>';
tr.appendChild(td);
}
//5.删除操作
var as = document.querySelectorAll('a');//获取所有a标签
for (i = 0; i < as.length; i++) {
as[i].onclick = function() {//每个a标签都要点击故而循环
tbody.removeChild(this.parentNode.parentNode)//删除的是行,该行是tbody的儿子,是a标签的爸爸(td)的爸爸(tr)
}
}
</script>
</body>
5、创建元素的三种方法
(1)document.write()
<body>
<button>点击</button>
<p>白龙网</p>
<script>
var btn = document.querySelector('button');
btn.onclick = function() {
//直接把内容写入页面的内容流,文档流执行完毕后,会导致页面全部重绘
document.write('<div>drupal</div>');
}
</script>
</body>
(2)innerHTML
<body>
<div class="top"></div>
<div class="bottom"></div>
<script>
var div = document.querySelector('.top');
div.innerHTML = '<a href= "">白龙网</a>';
</script>
</body>
<body>
<div></div>
<script>
for (i = 0; i <= 100; i++) {
var div = document.querySelector('div');
//用加号连字符,把循环添加的a标签连接到一起
div.innerHTML += '<a href= "/">白龙网</a>' + '<br />';
}
</script>
</body>
(3)appendChild('')
<body>
<div></div>
<script>
var a = document.createElement('a');
var div = document.querySelector('div');
div.appendChild(a);
</script>
</body>
for (i = 0; i <= 1000; i++) {
var a = document.createElement('a');
var div = document.querySelector('div');
div.appendChild(a);
}
innerHTML与appendChild()创建单个元素他们之间没有太大的区别;但是创建多个元素时,创建效率就有明显的区别了。
使用innertHTML创建元素,不采用拼接字符串,采用数组的形式,该方法比createElement()方法快,但是结构相对复杂些,例如,把字符串放入数据,再把数组转化为字符串等操作。
使用createElement虽然时间慢了些,但是结构消清晰,获取元素,创建元素,追加元素,一步到位,结构更加清晰。