🏆节点操作
我们获取元素通常有两种方式:
利用DOM提供的方法获取元素 和 利用节点层级关系获取元素
前者逻辑性不强但是繁琐;后者逻辑性强但是兼容较差,今天讲解节点操作
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。HTML DOM树中的所有节点均可通过JavaScript进行访问,所有 HTML 元素(节点)均可被修改,也可以创建和删除。
⚽概述
一般地,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和 nodeValue(节点值)这三个基本属性。
①元素节点 nodeType 为1
②属性节点 nodeType 为2
③文本节点 nodeType 为3(文本节点包含文字、空格、换行等)
⚾节点层级
利用 DOM 树可以把节点划分为不同的层级,常见的是 父子兄 层级关系。
1、父节点
node.parentNode
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="grandfather">
<div class="father">
<div class="son"></div>
</div>
</div>
<script>
// 父节点 parentNode
var son = document.querySelector('.son');
// var father = document.querySelector('.father')
// 得到的是离元素最近的父级节点,如果找不到父级节点就返回为null
console.log(son.parentNode);
</script>
</body>
</html>
2、子节点
parentNode.childNodes (标准)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
// DOM提供获取子元素的方法
var ul = document.querySelector('ul');
var lis = document.querySelectorAll('li');
// 子节点 childNodes 所有的子节点 包含 元素节点 文本节点等。
console.log(ul.childNodes);
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
</script>
</body>
</html>
parentNode.childNodes 返回包含指定节点的子节点集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点、文本节点等。
如果只想获得里面的元素节点,则需要专门处理,一般不提倡使用 childNodes
var ul = document.querySelector('ul');
for(var i = 0;i<ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType == 1){
console.log(ul.childNodes[i]);
}
}
parentNode.children(非标准)
parentNode.children是一个只读属性,返回所有的子节点元素,它只返回子元素节点,其余节点不返回,虽然children是一个非标准,但是得到了各个浏览器的支持,我们可以放心使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var ul = document.querySelector('ul');
console.log(ul.children);
</script>
</body>
</html>
parentNode.firstChild parentNode.firstElementChild
parentNode.lastChild parentNode.lastElementChild
firstChild和lastChild返回第一个和最后子节点,找不到则返回null,前者返回包含所有节点。后者只返回子元素节点,但有兼容性问题,IE9以上才支持。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var ul = document.querySelector('ul');
// firstChild和lastChild 第一个和最后一个子节点 包含所有节点
console.log(ul.firstChild);
console.log(ul.lastChild);
// firstElementChild和lastElementChild 返回第一个和最后一个元素节点
console.log(ul.firstElementChild);
console.log(ul.lastElementChild);
</script>
</body>
</html>
实际开发的写法,既没有兼容性问题又返回第一个子元素
console.log(ul.children[0]);
console.log(ul.children.length - 1);
3、兄弟节点
node.nextSibling(下一个兄弟节点) node.previousSibling(上一个兄弟节点)
返回当前元素的下一个和上一个兄弟节点,找不到则返回null,包含所有节点。
node.nextElementSibling(下一个兄弟元素节点) node.previousElementSibling(上一个兄弟元素节点)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
// 1.下一个和上一个兄弟节点,包含元素节点或者文本节点等等
console.log(div.nextSibling);
console.log(div.previousSibling);
// 2.得到下一个和上一个兄弟元素节点 有兼容性问题,IE9以上支持
console.log(div.nextElementSibling);
console.log(div.previousElementSibling);
</script>
</body>
</html>
自己封装一个兼容性函数,解决兼容性问题。
function getNextElementSibling(element){
var el = element;
while(el = el.nextSibling){
if(el.nodeType ===1 ){
return el;
}
}
return null;
}
🏀创建添加节点
document.createElement('tagName') (创建节点)
node.appendChild(child) (添加后置节点)
node.insertBefore(child,指定元素) (添加前置节点)
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所有我们也称为动态创建节点;node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素;node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的before伪元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>123</li>
</ul>
<script>
// 1.创建元素节点
var li = document.createElement('li');
// 2.添加后置元素节点 node.appendChild(child) node父级 child 子级 后面追加元素类似数值中的push
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3.添加前置节点 node.insertBefore(child,指定元素)
var lili = document.createElement('li');
ul.insertBefore(lili,ul.children[0])
</script>
</body>
</html>
🏈删除节点
node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>删除</button>
<ul>
<li>我</li>
<li>你</li>
<li>他</li>
<li>她</li>
</ul>
<script>
// 1.获取元素
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
// 2.点击按钮依次删除元素
btn.onclick = function(){
if(ul.children.length == 0){
btn.disabled = 'true';
return false;
}
ul.removeChild(ul.children[0])
}
</script>
</body>
</html>
🏉复制节点
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点。注意:如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点;括号为true 深拷贝,复制标签也复制里面的内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1.node.cloneNode();括号为空或者里面是false 浅拷贝,只复制标签不复制里面的内容
// 1.node.cloneNode(true);括号为true 深拷贝,复制标签也复制里面的内容
var lili = ul.children[0].cloneNode(true)
ul.appendChild(lili);
</script>
</body>
</html>
🎾三种创建元素的方式和区别
document.write() 创建元素
是直接将内容写入页面的内容流,但是文档流执行完毕,它会导致页面重绘。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>按钮</button>
<div>123</div>
<script>
var btn = document.querySelector('button');
btn.onclick = function (){
document.write('<div>1234</div>')
}
</script>
</body>
</html>
innerHTML 创建元素
创建多个元素效率更高(不要拼接字符串,采取数组的形式拼接),结构稍微复杂
document.createElement() 创建元素
createElement() 创建多个元素效率会低一点点,但是结构更加清晰
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="inner"></div>
<div class="create"></div>
<script>
// 1.innerHTML创建元素
var inner = document.querySelector('.inner');
for(var i = 0;i<100;i++){
inner.innerHTML += '<a href="#">百度</a>';
}
var arr = [];
for(var i = 0;i<100;i++){
arr.push('<a href="#">百度</a>')
}
inner.innerHTML = arr.join('');
// 3.document.createElement() 创建元素
var create = document.querySelector('.create');
for(var i = 0;i<100;i++){
var a = document.createElement('a');
create.appendChild(a);
}
</script>
</body>
</html>