DOM 操作
节点的操作
获取节点
parentNode
:父节点(最高的父节点为 document)childNodes
:所有子节点,返回类数组firstChild
:第一个子节点lastChild
:最后一个子节点nextSibling
:下一个兄弟节点previousSibling
:上一个兄弟节点
- 兼容所有浏览器
<ul id="box">
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
<script>
console.log(box.parentNode); // <body> ... <//body>
console.log(box.childNodes); // NodeList(7) [text, li#con1, text, li#con2, text, li#con3, text]
console.log(box.firstChild); // #text
console.log(box.lastChild); // #text
console.log(box.nextSibling); // #text
console.log(box.previousSibling); // #text
</script>
text
:为文本节点,这里表示空格、换行
获取元素节点
parentElement
:父元素节点children
:子元素节点,返回类数组firstElementChild
:第一个子元素节点lastElementChild
:最后一个子元素节点nextElementSibling
:下一个兄弟元素节点previousElementSibling
:上一个兄弟元素节点
- 除了
children
,IE8 及以下都不兼容
<ul id="box">
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
<script>
console.log(box.parentElement); // <body> ... <//body>
console.log(box.children); // HTMLCollection(3) [li#con1, li#con2, li#con3]
console.log(box.firstElementChild); // <li id="con1"></li>
console.log(box.lastElementChild); // <li id="con3"></li>
console.log(box.nextElementSibling); // <script> ... <//script>
console.log(box.previousElementSibling); // null
</script>
- 获取的都是元素节点,所以没有文本节点
创建节点
document.createElement()
:创建元素节点document.createTextNode()
:创建文本节点document.createComment()
:创建注释节点document.createDocumentFragment()
:创建文档片段
let eleNode = document.createElement('span');
console.log(eleNode); // <span></span>
let textNode = document.createTextNode('文本内容');
console.log(textNode); // "文本内容"
let comNode = document.createComment('注释内容');
console.log(comNode); // <!-- 注释内容 -->
let fraNode = document.createDocumentFragment();
console.log(fraNode); // #document_fragment
- 创建的节点不在 DOM 树上,所以不会被绘制到页面上
插入节点
parentNode.appendChild(child)
:在parentNode
的最后添加节点child
parentNode.insertBefore(frontChild, rearChild)
:把frontChild
添加到rearChild
前面
- 把创建的节点插入到页面上的节点内,就可以在页面上显示啦
eg:最新评论,将节点插到最前面:
<ul id="box">
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
<script>
let eleNode = document.createElement('li');
let textNode = document.createTextNode('文本');
eleNode.appendChild(textNode);
if (box.firstElementChild) { // 作为第一个节点
box.insertBefore(eleNode, box.firstChild);
} else {
box.appendChild(eleNode);
}
</script>
页面显示:
<ul id="box">
<li>文本</li>
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
**注意:**每一个节点都是唯一的,如果我们插入的节点是已经存在的节点,会删除之前的节点
删除节点
parent.removeChild(child)
:删除节点child
,会返回被删除的节点element.remove()
:删除节点element
,没有返回值
<ul id="box">
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
<script>
box.removeChild(con2);
</script>
页面显示:
<ul id="box">
<li id="con1"></li>
<li id="con3"></li>
</ul>
替换节点
parentNode.replace(newEle, oldEle)
:用节点newEle
代替节点oldEle
,会返回被替换的节点
<ul id="box">
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
<script>
let liNode = document.createElement('li');
liNode.className = 'new';
box.replaceChild(liNode, con2);
</script>
页面显示:
<ul id="box">
<li id="con1"></li>
<li class="new"></li>
<li id="con3"></li>
</ul>
如果用 con1
替换 con2
,相当于删除 con2
其他
element.hasChildNodes()
:用于判断一个元素节点有没有子节点,有则返回true
,无则返回false
<ul id="box">
<li id="con1"></li>
<li id="con2"></li>
<li id="con3"></li>
</ul>
<script>
let result = box.hasChildNodes();
console.log(result); // true
result = con1.hasChildNodes();
console.log(result); // false
</script>
元素节点
常用属性
innerHTML
:获取元素节点的内容,可读可写;如果内容符合 HTML 格式,会被解析成标签innerTEXT
:获取元素节点的内容,可读可写;即使内容符合 HTML 格式,也不会被解析成标签
<div id="wrap1">123</div>
<div id="wrap2">123</div>
<script>
wrap1.innerHTML = '<h4>文本</h4>';
wrap2.innerText = '<h4>文本</h4>';
</script>
如果 wrap 内没有内容,则添加;有内容,则替换
获取内容时,
innerHTML
是获取里面的标签内容;innerText
是获取里面的文本内容
<ul id="wrap">
<li>香蕉</li>
</ul>
<script>
console.log(wrap.innerHTML) // <li>香蕉</li>
console.log(wrap.innerText) // 香蕉
</script>
我们可以利用该属性,减少页面重构和重绘的次数
方法 1:重构了 arr.length
次
<ul id="wrap"></ul>
<script>
let arr = ['苹果', '雪梨', '香蕉'];
let oLi;
for (let index = 0; index < arr.length; index++) {
oLi = document.createElement('li');
oLi.innerText = arr[index]; // 使用 innerText 就无需创建文本节点了
wrap.appendChild(oLi);
}
</script>
方法 2:使用字符串拼接,重构了 1
次
<ul id="wrap"></ul>
<script>
let arr = ['苹果', '雪梨', '香蕉'];
let oLi = '';
for (let index = 0; index < arr.length; index++) {
oLi += '<li>' + arr[index] + '</li>';
}
wrap.innerHTML = oLi;
</script>
方法 3:使用文档片段,重构了 1
次
<div id="wrap"></div>
<script>
let arr = ['苹果', '雪梨', '香蕉'];
let oLi, oFrag;
oFrag = document.createDocumentFragment();
for (let index = 0; index < arr.length; index++) {
oLi = document.createElement('li');
oLi.innerText = arr[index];
oFrag.appendChild(oLi); // 先存储在文档片段节点中
}
wrap.appendChild(oFrag); // 将文档片段节点添加到 wrap 中
</script>
控制属性的方法
element.attributes.class
/element.attributes['class']
:获取元素节点的class
属性(键值对)element.attributes.class.name
element.attributes.class.value
等效于element.className
element.getAttribute('class')
等效于element.attributes.class.value
element.setAttribute('class', 'on')
:设置元素节点的class
属性值element.removeAttribute('class')
:删除元素节点的class
属性
上面的 class
可以换为其他属性名
获取 / 设置属性
1 方法
我们可以通过方法获取并修改元素的属性
element.getAttribute('属性名')
element.setAttribute('属性名', '属性值')
2 点语法
我们可以通过 .
获取并修改元素的属性
oImg.src = "images/2.jpg"; // 修改图片地址
oLianjie.href = "http://www.163.com"; // 修改超链接地址
oBox.value = "嘻嘻嘻嘻嘻"; // 修改表单的内容
oBox.style.color = 'red'; // 修改行内 CSS 样式
注意:class
属性需要通过 className
获取,因为 class
是保留字
oDiv.className = "da"; // 修改类名,会覆盖原来的类名
oBox.className += ' hide'; // 添加类名,注意前面要有空格
区别
①
.
无法获取并修改自定义的属性;setAttribute()
/getAttribute()
可以
<div id='box'></div>
let oBox = document.getElementById('box');
oBox.wu = 'super'; // 无效
oBox.setAttribute("su", "name");
console.log(oBox); // <div id='box' su='name'></div>
注意:.
的效率比较高,所以一般都使用 .
操作
②
.
获取的属性是一个对象。我们可以再通过.
获取子属性,eg:.style.color
getAttribute()
得到的是字符串
console.log(typeof oBox.style); // object
console.log(typeof oBox.getAttribute("style")); // string
③
getAttribute()
不需要避讳,比较直观
oBox.getAttribute('class')
oBox.className
.
获取的属性名要符合标识符规范。所以有连字符的属性名要写成小驼峰式
oBox.getAttribute('background-color')
oBox.style.backgroundColor
classList 属性
classList
是 H5 新增的属性,是一个类数组( IE9 及以下不兼容 )
用于设置元素节点的类名,有几个常用的方法:
add('value')
:添加类名value
,不会重复添加remove('value')
:删除类名value
contains('value')
:查询类名value
,返回布尔值toggle('value')
:查询类名value
。有则删除,并返回false
;无则添加,并返回true
replace('old', 'new')
:用new
替换类名old
自定义属性
H5 新增了自定义属性,需要以 data-
开头( IE10 及以下不兼容 )
元素节点有一个 dataset
属性用来获取和设置自定义属性
<div id="box" data-myName="man"></div>
let div = document.getElementById('box');
// 获取自定义属性值
console.log(div.dataset); // DOMStringMap {myname: "man"}
// 修改自定义属性值
div.dataset.myname = 'super'; // 属性名都是小写,不需要驼峰
// div.dataset['myname'] = 'super' // 两语句等效
console.log(div.dataset); // DOMStringMap {myname: "super"}
console.log(div); // <div id="box" data-myname="super"></div>
这里的
myname
必须都使用小写,myName
会在 HTML 中变成data-my-name
let div = document.getElementById('box');
// 获取自定义属性值
console.log(div.dataset); // DOMStringMap {myname: "man"}
// 修改自定义属性值
div.dataset.myName = 'super'; // 属性名都是小写,不需要驼峰
// div.dataset['myName'] = 'super' // 两语句等效
console.log(div.dataset); // DOMStringMap {myname: "man", myName: "super"}
console.log(div); // <div id="box" data-myname="man" data-my-name="super"></div>