一、DOM
是HTML和XML文档的编程接口,定义了访问和操作HTML和XML文档的标准方法。
DOM以树型目录结构表达HTML和XML文档的,每一个节点就是一个DOM元素。
二、DOM节点
(一)节点层次
节点层次分为父子节点和同胞节点两种。在节点树中,顶端节点被称为根(root),每个节点都有父节点、除了根(它没有父节点),一个节点可拥有任意数量的子节点,同胞节点是拥有相同父节点的节点,也叫兄弟节点
(二)元素节点:标签
1、属性节点:标签的属性
2、文本节点:标签后的换行符
3、文档节点:document
(三)DOM节点的名称(nodeName)
首先写一段测试的相关代码
<div class="wrapper">
<div class="box">
<div id="content" title="标题">这里是测试内容</div>
<p style="color:red;background-color:gray;font-size:30px;">hello</p>
</div>
</div>
1、元素节点 标签名相同
<script>
console.log(document.getElementById('content').nodeName);
</script>
getElementById() 方法可返回对拥有指定 ID 的第一个对象的引用。
nodeName就是节点名称。
返回结果为:DIV,就是div,元素的标签。
2、属性节点 属性名相同
<script>
console.log(document.getElementById('content').getAttributeNode('title').nodeName);
</script>
getAttributeNode() 方法从当前元素中通过名称获取属性节点。
返回结果为:title
3、文本节点 #text
<script>
console.log(document.getElementById('content').childNodes[0].nodeName);
</script>
childNodes 属性返回包含被选节点的子节点的 NodeList。
返回结果为:#text
虽然一开始我也不太明白此处,但如果不懂,其实可以进行一下测试,比如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="wrapper">
<div id="content" title="标题"> <p>test1</p> <p>test2</p> <p>test3</p> </div>
</div>
<script>
var arr=document.getElementById('content').childNodes;
for(var i =0;i<arr.length;i++){
console.log(arr[i].nodeName)
}
</script>
</body>
</html>
结果为:
但如果代码为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="wrapper">
<div id="content" title="标题"><p>test1</p><p>test2</p><p>test3</p></div>
</div>
<script>
var arr=document.getElementById('content').childNodes;
for(var i =0;i<arr.length;i++){
console.log(arr[i].nodeName)
}
</script>
</body>
</html>
结果会变为:
注意:仔细观察,会变成这样的结果在于第一条代码中,每个p便签前后都有空格,第二个代码,p标签前后没有空格,所以,代码的轻微修改得出的结论都会不同,无论是空格和回车第一条都会显示#test。
4、文档节点 #document
<script>
console.log(document.nodeName) ;
</script>
返回结果为:#document
(四)DOM节点的值(nodeValue)
1、元素节点 undefined 或 null
console.log(document.getElementById('content').nodeValue)
nodeValue 属性根据节点的类型设置或返回节点的值。
返回的结果为null;
2、属性节点 属性值
console.log(document.getElementById('content').childNodes[0].nodeValue)
返回结果为:这里是测试内容
3、文本节点 文本内容
console.log(document.getElementById('content').getAttributeNode('title').nodeValue)
返回结果为:标题
(五)DOM节点的类型(nodeType)
1、元素 1
console.log(document.getElementById('content').nodeType);
返回结果为:1
2、属性 2
console.log(document.getElementById('content').getAttributeNode('title').nodeType);
返回结果为:2
3、文本 3
console.log(document.getElementById('content').childNodes[0].nodeType);
返回结果为:3
4、注释 8
5、文档 9
console.log(document.nodeType)
返回结果为:9
三、节点操作
首先先写一些测试代码
<div id="box">box</div>
<p>p01</p>
<p>p02</p>
<div class="box">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
<input type="text" name="userName">
(一)获取节点
1、通过ID获取节点 【返回具体某个节点】:document.getElementById(ID名)
var box = document.getElementById('box');
box.style.color = 'red';
2、通过标签名获取节点 【返回节点数组,即使只有一个】:document.getElementsByTagName(标签名)
var pAll = document.getElementsByTagName('p');
pAll[0].style.fontSize = '30px';
3、通过标签的name值获取节点 【返回节点数组】:document.getElementsByName(Name名)
var names = document.getElementsByName('userName');
names[0].value = '张三';
4、通过class值来获取节点 【返回节点数组】:document.getElementsByClassName(Class名)
var boxes = document.getElementsByClassName('box');
for(var i in boxes){
boxes[i].innerHTML = 'hahaha....'
}
innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML。
5、根据选择器返回找到结果集中的第一个:document.querySelect(“选择器”)
console.log(document.querySelector('p')) // 标签
console.log(document.querySelector('.box'))// 类
console.log(document.querySelector('#box'))// ID
6、根据选择器返回找到的结果集,是个节点数组:document.querySelectAll(“选择器”)
console.log(document.querySelectorAll('p')) // 标签
console.log(document.querySelectorAll('.box'))// 类
(二)创建DOM节点
首先写一段测试代码
<style>
.wrapper{
color: red;
font: bold 18px 黑体;
background-color: #999999;
}
.box{
border: 1px solid blue;
}
</style>
1、创建元素节点:document.createElement(‘标签名’);
var el = document.createElement('p');
console.log(el);
2、创建文本节点:document.createTextNode(‘文本内容’);
var txt = document.createTextNode('这个节点是动态创建的');
console.log(txt);
3、创建属性节点:document.createAttribute(‘属性名’);属性节点名.value = ‘属性值’; // 为属性设置值
var attr = document.createAttribute('class');// 添加属性名
attr.value = 'wrapper box'; // 为属性设置值
console.log(attr);
4、关联以上三个节点
元素节点名.appendChild(文本节点名); // 在元素节点上添加文本节点
元素节点名.setAttributeNode(属性节点名); // 在元素节点上添加属性节点
document.body.appendChild(元素节点名); // 将创建的节点添加到文档中
el.appendChild(txt); // 在元素节点上添加文本节点
el.setAttributeNode(attr); // 在元素节点上添加属性节点
console.log(el);
document.body.appendChild(el); // 将创建的元素节点添加到文档中
简洁写法:
var oDiv = document.createElement('div'); // 创建元素节点
oDiv.setAttribute('class','wrapper box'); // 为元素节点添加属性及属性值
oDiv.innerHTML = '创建DOM元素的简洁写法'; // 为元素节点设置文本内容
document.body.appendChild(oDiv); // 将创建的元素节点添加到文档中
四、插入节点
测试代码
<ul class="list">
<li>li1</li>
<li>li2</li>
<li>li3</li>
<li>li4</li>
</ul>
首先创建一个新的li标签
var li = document.createElement('li');
var txt = document.createTextNode('这是新创建的li标签');
li.appendChild(txt);
appendChild() 方法可向节点的子节点列表的末尾添加新的子节点。
1、插入内部的尾部:父节点.appendChild(创建的节点)
var list = document.getElementsByClassName('list')[0];
list.appendChild(li);
2、插入内部的某个前面:父节点.insertBefore(创建的节点,已知的子节点)
var ul = document.getElementsByClassName('list')[0];
var oLi = ul.getElementsByTagName('li')[2];
ul.insertBefore(li, oLi);
五、替换节点
测试代码
<div class="box">box</div>
<strong>strong</strong>
父节点.replaceChild(新节点,老节点)
此次完成一个需求:将strong标签修改成
<p style='color:pink;border:2px dotted #000;'>这是修改后的节点及内容</p>
var newP = document.createElement('p');
newP.setAttribute('style','color:pink;border:2px dotted #000;');
newP.setAttribute('title','节点修改');
newP.innerHTML = '这是修改后的节点及内容';
var oBody = document.body; // 对于节点的获取,最好缓存到内存变量中
var oldStrong = document.getElementsByTagName('strong')[0];
oBody.replaceChild(newP, oldStrong);
六、克隆节点
测试代码
<div class="box">
<strong>strong</strong>
<span>span</span>
</div>
需要被复制的节点. cloneNode(true/false)
true: 复制当前节点以及所有子节点(深度克隆)
false: 仅复制当前节点(浅克隆)
1、深度克隆: 包含子节点一起克隆。
var box = document.getElementsByClassName('box')[0];
var deepClone = box.cloneNode(true);
document.body.appendChild(deepClone);
2、浅克隆: 只会将找到的这个节点克隆,子节点不会克隆
var shallowClone = box.cloneNode(false);
document.body.appendChild(shallowClone);
注意变化:
浅克隆前:
浅克隆后:
仔细观察会发现,多了一条div class=‘box’,这边是浅克隆的精妙之处
七、删除节点
测试代码
<div class="box">
<strong>strong</strong>
<span>span</span>
</div>
<ul>
<li>li1</li>
<li>li2</li>
<li>li3</li>
<li>li4</li>
<li>li5</li>
</ul>
1、删除当前节点及子节点:节点.remove();
var box = document.getElementsByClassName('box')[0];
box.remove();
2、删除子节点:父节点.removeChild(子节点)
var span = box.getElementsByTagName('span')[0];
box.removeChild(span);
3、删除ul中所有的li标签
var ul = document.getElementsByTagName('ul')[0];
var lis = ul.getElementsByTagName('li');
for(var i=lis.length-1;i>=0;i--){
ul.removeChild(lis[i]);
}
此处注意,如果for循环内使用递加操作,也就是for(var i=0;i<lis.length;i++),是删除不完li标签的,比如第一个标签下标是0,i=0,删除第一个后,i=1,但第二个标签下标就会变成0,自动上移一位,i=1的时候,删除的就是第三个标签,就不会删除完。
for(var i=0;i<lis.length;i++){
ul.removeChild(lis[i]);
}
但如果想要删除完,可以在代码内加入- -i这条语句,但会引起死循环,因为i永远是0,为了避免这一情况,最好使用递减操作
八、节点属性操作
测试代码
<style>
img{
width: 200px;
height: 150px;
display: block;
}
</style>
<button id="btn">切换图片</button>
<img src="images/bg1.jpg" data-src="images/bg2.jpg" alt="图片" />
<img data-src="images/bg2.jpg" alt="图片" />
1、获取属性值
DOM节点.属性名 // 不能获取用户自定义属性的值
var img = document.getElementsByTagName('img')
console.log(img[0].src);
console.log(img[0].alt);
DOM节点.getAttribute(属性名) // 获取所有属性(用户自定义属性)的值
console.log(img[0].getAttribute('src'));
console.log(img[0].getAttribute('data-src'));
2、设置属性值
DOM节点.属性名 = 属性值 // 不能设置用户自定义属性的值
img[1].src = 'images/bg1.jpg'
DOM节点.setAttribute(属性名, 属性值) // 设置所有属性(用户自定义属性)的值
document.getElementById('btn').onclick = function () {
var url = img[0].getAttribute('data-src');
img[0].setAttribute('src',url)
}
效果:点击按钮后可以切换图片(只能切换一次)
var tag=1;
document.getElementById('btn').onclick = function () {
if(tag==1){
var url = img[0].getAttribute('data-src');
img[0].setAttribute('src',url)
tag=0;
}
else if(tag==0){
var url ='images/bg1.jpg';
img[0].setAttribute('src',url)
tag=1;
}
}
效果可切换多次
3、删除属性值
DOM节点.属性名 = ‘’ // 不能删除用户自定义属性
img[1].src = '';
DOM节点.removeAttribute(属性名) // 删除所有属性(用户自定义属性)
img[1].removeAttribute('src');
九、节点文本操作
测试代码
<button id="btn"><span>这是</span>切换图片</button>
<form action="">
<input type="text" name="txt" value="这是表单文本框的内容"><br>
<input type="radio" name="sex" value="1">男
<input type="radio" name="sex" value="0">女 <br>
<input type="checkbox" name="hobby" value="码代码">码代码
<input type="checkbox" name="hobby" value="听音乐">听音乐
<input type="checkbox" name="hobby" value="打游戏">打游戏
<input type="checkbox" name="hobby" value="其他">其他
<br><input type="button" value="提交" id="ok">
</form>
(一)获取文本
1、节点.innerHTML //获取节点下的所有内容包含了标签
console.log(document.getElementById('btn').innerHTML);
2、节点.innerText // 获取节点下的文本内容,会过滤掉标签
console.log(document.getElementById('btn').innerText);
返回结果为:这是切换标签
3、节点.value // 获取input输入框等表单控件的内容
console.log(document.getElementsByName('txt')[0].value)
console.log(document.forms[0].txt.value)
console.log(document.querySelector('input').value)
以上三条返回结果相同:这是表单文本框的内容
4、节点.getAttribute(“value”) //value是表单输入框的属性,可以使用getAttribute获得value值
console.log('value:' + document.forms[0].txt.getAttribute('value'))
返回结果为:value:这是表单文本框的内容
(二)设置文本
1、节点.innerHTML= “文本内容” // 会翻译html标签
document.getElementById('btn').innerHTML = '这是一个<strong>命令按钮</strong>'
2、节点.innerText = “文本内容” // 不会翻译html标签
document.getElementById('btn').innerText = '这是一个<strong>命令按钮</strong>'
3、节点.value = 值
document.forms[0].sex.value = 0;
document.forms[0].hobby.value = '码代码';// 不能通过value设置复选框的某项被选中
document.forms[0].hobby[1].checked = true;
document.forms[0].hobby[2].checked = true;
4、节点.setAttribute(“value”,值) // 因为value是属性,所以也可以中这个方法设置内容
document.forms[0].hobby[0].setAttribute('value','1')
(三)删除文本
1、节点.innerHTML= “”
document.getElementById('btn').innerHTML = ''
2、节点.innerText = “”
document.getElementById('btn').innerText = ''
3、节点.value = “”
document.forms[0].hobby[0].value = ''
4、节点.removeAttribute(“value”);
document.forms[0].hobby[0].removeAttribute('value')
**
十、DOM节点样式操作
测试代码
<style>
.p-style{
color: red;
background-color: gray;
font-size: 30px;
font-weight: bold;
}
.demo{
border: 2px solid #00f;
}
</style>
<p class="test p-style">这是一段测试文本</p>
<p class="test">这是一段测试文本</p>
**
(一)操作样式class
1、获取class
(1)节点.className 获取节点的所有class
console.log(document.getElementsByClassName('test')[0].className);
(2)节点.getAttribute(“class”) 获取节点的所有class
console.log(document.querySelector('.test').getAttribute('class'));
以上返回结果相同都是:test p-style
2、设置class
(1)节点.className = 值
document.getElementsByTagName('p')[1].className = 'p-style'
(2)节点.setAttribute(“class”,值)
document.getElementsByTagName('p')[1].setAttribute('class', 'demo test p-style');
3、其它方法
(1)节点.classList.add(value); //为元素添加指定的类
document.getElementsByTagName('p')[1].classList.add('aaa');
(2)节点.classList.contains(value); // 判断元素是否含有指定的类,如果存在返回true
(3)节点.classList.remove(value); // 删除指定的类
if(document.getElementsByTagName('p')[1].classList.contains('p-style')){
document.getElementsByTagName('p')[1].classList.remove('p-style')
}else{
document.getElementsByTagName('p')[1].classList.add('p-style')
}
(4)节点.classList.toggle(value); // 有就删除,没有就添加指定类
var dom = document.getElementsByTagName('p')[1];
dom.onclick = function(){
dom.classList.toggle('p-style'); // 切换样式
}
(二)操作内联样式
测试代码
<p style="color:red;">这是一段测试文本</p>
<p style="color:blue;font-size: 28px;border:1px solid #eee;position:relative;left: 100px;top:200px;overflow:hidden;">这是一段测试文本</p>
<div>div</div>
1、获取内联样式
(1)节点.style.样式属性名 // 获取某个具体的内联样式
var pDom = document.querySelectorAll('p');
console.log(pDom[0].style.color)
console.log(pDom[1].style.fontSize)
(2)节点.style.cssText // 获取某个节点的所有内联样式,返回字符串
console.log(pDom[0].style.cssText)
console.log(pDom[1].style.cssText)
2、设置内联样式
(1)节点.style.样式属性名 = 属性值 // 设置某个具体的内联样式
pDom[0].style.color = 'pink'
pDom[1].style.fontSize = '10px'
(2)节点.style.cssText = 属性值或属性值列表 // 设置某个节点的所有内联样式
document.querySelector('div').style.cssText = 'color: white'
document.querySelector('div').style.cssText = 'color: white;background-color: blue;'