JavaScript DOM
DOM
在javascript中所有的节点类型都继承Node类型,因此所有的类型都享有基本的属性和方法。每个节点都有nodeType属性,表示该节点的类型,节点类型由定义在Node类型上的12个数值常量表示,较为常用的是前3个
Node.ELEMENT_NODE (1) 对于元素来讲,nodeName是元素的标签名,nodeValue始终是null
Node.ATTRIBUTE_NODE(2)
Node.TEXT_NODE(3)
节点关系
每一个节点都有一个childNodes属性,它实际上是包含着一个nodeList的实例,nodeList实例是一个类数组,它也有length属性,它可以使用中括号或者使用item( )方法来访问NodeList中的元素
每一个节点都有一个parentNodes属性,指向DOM树种的父元素。childNodes中的所有节点都有同一个父元素,因此它们的parentNodes属性指向同一个节点。另外,childNodes列表中的每一个节点都是同一列表中其它节点的同胞节点。而使用previousSibling和nextSibling可以在这个列表的节点中导航。
父节点和它的第一个以及最后一个子节点有专门的属性,firstChild和lastChild
someNode.childNodes[0]=someNode.firstChild
someNode.childNodes[someNode.childNodes.length-1]=someNode.lastChild
如果父节点只有一个子节点,那么someNode.firstChild=someNode.lastChild
如果没有子节点,那么firstChild和lastChild都等于null
hasChildNodes(),如果这个方法返回true,则说明节点有一个或多个子节点
操纵节点
插入节点 appendChild() , 在子节点末尾添加节点
insertBefore(要插入的节点,参照节点),在特定位置插入节点
replaceChild(替换节点,被替换节点) 替换节点
removeChild(),与replaceChild()方法一样,通过替换,移除的节点从技术上来讲仍然被同一个文档所拥有,但文档中没有了它的位置
代码展示
<body>
<div class='contain'><p>第一个子节点</p><p>第二个子节点</p><p>第三个子节点</p><div>最后一个子节点</div></div>
<script>
let contain=document.querySelector('.contain')
console.log(contain instanceof Object) // 获取到该文档对象
console.log('------')
// dom中所有的节点都继承自Node类型,都拥有最基本的Node节点的属性和方法
console.log(contain.nodeName) // DIV
console.log(contain.nodeType) //1
console.log(contain.nodeValue) //null
console.log('------')
// childNodes,在删除所有子元素节点间的空格后,方能获取到正常的子元素序列,若非如此,节点间的空间会被当成<text></text>处理
console.log(contain.childNodes) // 每个节点都有childNodes属性
console.log(contain.childNodes instanceof Object) // 文档对象的childNodes属性返回1个类数组,本质是1个对象
console.log(contain.childNodes.length) // 元素的子节点长度
console.log(contain.childNodes[0]===contain.firstChild) // 使用数组的中括号获取第1个子节点
console.log(contain.childNodes.item(2)) // 使用item()方法获取第3个子节点
console.log(contain.childNodes[contain.childNodes.length-1]===contain.lastChild) // 元素的最后一个子节点
console.log(contain.lastChild.previousSibling) // previousSibling 导航到前一个子节点
console.log(contain.firstChild.nextSibling) // nextSibling 导航到后一个子节点
console.log('------')
// 可以使用for of来遍历该类数组
for(item of contain.childNodes) {
console.log(item)
}
// 创建文本节点,元素节点,使用appendChild插入到子节点末尾位置
let newText=document.createTextNode('新插入的子节点')
let divAttri=document.createElement('div')
divAttri.appendChild(newText)
contain.appendChild(divAttri)
// 在特定位置插入子节点
let newText1= document.createTextNode('新插入的子节点1')
let divAttri1= document.createElement('div')
divAttri1.appendChild(newText1)
contain.insertBefore(divAttri1,divAttri)
// 替换节点
let newText2= document.createTextNode('新插入的子节点2')
let divAttri2 = document.createElement('div')
divAttri2.appendChild(newText2)
contain.replaceChild(divAttri2,divAttri1)
// 移除节点
contain.removeChild(divAttri2)
</script>
</body>
DOM扩展
querySelector(),该方法接收css选择符参数,返回匹配该模式的第一个后代元素,如果没有匹配项则返回null
querySelectorAll(),该方法和querySelector()一样,也接受一个用于查询的参数,它返回所有匹配的节点,返回的是一个NodeList的静态实例,返回的NodeList对象可以通过for-of循环、item()方法或中括号语法取得个别元素
有些浏览器会把元素间的空格当成空白节点,这会导致childNodes和firstChild等属性上的差异,为了弥补这种差异,同时不影响DOM规范,W3C规范定义了新的属性
childElementCount , 返回子元素数量(不包含文本节点和注释)
firstElementChild , 指向第一个Element类型的子元素(Elememt版firstChild)
lastElementChild , 执行最后一个Element类型的子元素(Element版lastChild)
previousElementSibling , 指向前一个Element类型的同胞元素(Element版previousSibling
)
nextElementSibling , 指向向后一个Element类型的同胞元素(Element版nextSibling)
classList属性,要操作类名,可以通过className属性实现添加、删除和替换class,childList实例的方法
add(value),向类名列表种添加指定的字符串值value,如果这个值存在则什么都不做
contains(value),返回布尔值,表示给定的value是否存在
remove(value),从类名列表中删除指定的字符串值value
toggle(value),如果类名列表中存在指定的value,则删除,如果不存在,则添加
插入标记
innerHTMl属性
再读取innerHTML属性时,会返回元素所有后代的HTMl字符串、包括元素、注释和文本节点。再写入innerHTML时,则会根据提供的值以新的DOM子树替代元素中原来包含的所有节点
outerHTML属性
读取outerHTML属性时,会返回调用它的元素(及所有的后代元素)的HTML字符串,在写入outerHTML属性时,调用它的元素会被传入的HTML字符串经解释后生成的DOM子树所取代
innerText属性
innerText属性对应元素中包含的所有文本内容,在用于写入值时,innerText会移除元素的所有后代并插入一个包含该值的文本节点
outerText属性
outerText与innerText类似,在读取文本时,outerText与innerText实际上返回同样的内容,但是在写入文本值时,outerText就大不相同了,outerText不止会移除所有的后代节点,而是会替换整个元素,本质上来讲,这相当于用新的文本节点替代outerText所在的元素,此时,原来的元素会与文档脱离关系,因此变得无法访问
代码展示
<body>
<div>DOM扩展解决了元素子节点间的空格问题,更好地直接获取到元素节点,而非空格</div>
<div id='box' class='todo work'>
<div style='color:lightblue; font-size:20px;'>the fisrt item</div>
<div>the second item</div>
<div>the third item</div>
<div>the fourth item</div>
<p>thie fifth paragraph</p>
</div>
<script>
let box=document.getElementById('box')
// 获取子节点数量,子元素节点数量
// 正常的结构布局下,元素的子节点数量>>子元素节点数量
// 该处的子节点数量=子元素节点间的空格+与父节点间的空格+子元素节点的数量=11
// 该处的子元素节点数量=5
console.log(box.childNodes.length)
console.log(box.childElementCount)
// 获取元素的第一个子元素节点,最后一个子元素节点,记忆在元素节点间导航
console.log(box.firstChild) //空格节点
console.log(box.firstElementChild)
console.log(box.lastElementChild)
console.log(box.firstElementChild.nextElementSibling)
console.log(box.lastElementChild.previousElementSibling)
// 类名操作,获取类名,添加类名,移除类名,动态操作类名,检查类名
console.log(box.classList)
box.classList.add('made')
box.classList.add('move')
box.classList.remove('made')
box.classList.toggle('move')
let ismove=box.classList.contains('move')
console.log(ismove)
// 使用classList属性,toggle方法动态为子元素添加背景颜色
let boxItem=document.querySelectorAll('#box>div')
for(i=0; i<boxItem.length; i++) {
boxItem[i].onclick=function(){
this.classList.toggle('active')
}
}
console.log(boxItem)
// 插入标记
console.log(box.innerHTML) // 返回元素所有后代元素及文本节点
console.log(box.outerHTML) // 返回调用元素本身及所有后代元素及文本节点
console.log(box.innerText) // 返回所有后代元素文本节点
console.log(box.outerText) // 与innerText返回结果相同
console.log(box.firstElementChild.innerText)
// box.innerHTML='<div>重新洗牌后代元素</div>' // 替换掉所有后代元素
// box.outerHTML='<div>outerHTML的样子</div>' // 与innerHTNL效果一致
box.firstElementChild.innerText='覆盖原来的文本' // 替换原来的文本
// box.firstElementChild.outerText='outerText,写入时的样子' // 替换文本所在的元素,改变了整个元素
// style对象上的属性和方法
console.log(box.firstElementChild.style.cssText) // 读取该子元素的style样式
box.lastElementChild.style.cssText='color:blue; font-size:24px;' // 向该元素写入style样式
console.log(box.lastElementChild.style.length) // 读取该元素的css属性个数
</script>
</body>
DOM2和DOM3
规范在style对象上的属性和方法,这些属性和方法提供了元素style属性的信息并支持修改
cssText , 包含style属性中的css代码
length , 应用给元素的css属性数量
偏移尺寸
offsetHeight , 元素在垂直方向上占用的像素尺寸,包括元素高度(内容+内边距),上下边框高度,水平滚动条高度(如果有的话)
offsetWidth , 元素在水平方向上占用的像素尺寸,包括元素宽度(内容+内边距), 左右边框宽度,垂直滚动条宽度
offsetLeft , 元素左边框外侧距离包含元素的左边框内侧的距离
offsetTop , 元素上边框外侧距离包含元素上边框内侧的距离
客户端尺寸
元素的客户端尺寸包含元素内容及其内边距所占用的空间 ,不包括边框 ,实际代表的是元素内部的空间
clientHeight 内容区高度+上下内边距高度
clientWidth 内容去宽度+左右内边距宽度
滚动尺寸
scrollHeight 没有滚动条出现时,内容区的总高度
scrollWidth 没有滚动条出现时,内容区的总宽度
scrollTop 内容区顶部隐藏的像素数 即是内容区顶部滚动的距离
scrollLeft 内容区左侧隐藏的像素数 即是内容去左侧滚动的距离