一、DOM简介
网页其实是一个树
JS用document来操作网页,这就是Document Object Model 文档对象模型
二、获取元素的API
-
获取任意元素
window.idxxx // 或者直接idxxx document.getElementById('idxxx') document.getElementsByTagName('div')[0] document.getElementsByClassName('red')[0] document.querySelector('#idxxx') document.querySelectorAll('.red')[0] //最后两个比较常用 -
获取html元素
document.documentElement -
获取head元素
document.head -
获取body元素
document.body -
获取窗口(窗口不是元素)
window -
获取所有元素
document.all//document.all是第六个false值(0,NaN,'',null,undefined)
三、获取元素的原型
获取到的元素是一个对象
3.1节点和元素的区别
节点Node包括以下几种,可以通过x.nodeType来得到
- 元素Element,也叫标签Tag
- 文本Text
- 注释Comment
- 文档Document等等
3.2一个div的完整原型链
四、节点的增删改查
4.1增加节点
-
创建标签节点
let div1 = document.createElement('div') -
创建一个文本节点
text1 = document.createTextNode('你好') -
在标签里面插入文本
div1.appendChild(text1) div1.innerText = '你好' div1.textContent ='你好'-
创建的标签默认处于JS线程中,必须放在body或者head才会生效
-
document.body.appendChild(div1) //或者页面已知元素.appendChild(div1)
-
Q:页面中有div#test1,div#test2,div会出现在哪里
let div = document.createElement('div')
test1.appendChild(div)
test2.appendChild(div)
A:出现在test2里,一个元素不能出现在两个地方,除非复制一份(cloneNode)
4.2删除节点
parentNode.removeChild//旧方法,通过父节点删除
childNode.remove()//IE不兼容
4.3修改节点
- 修改属性
div.className = 'blue' //修改class
div.classList.add('red') //修改class
div.style = 'width:100px;color:blue' //修改style,全覆盖
div.style.width = '200px'//修改style的一一部分
div.style.backgroundColor = 'white' //用-隔开的全部用大写代替
div.dataset.x = 'frank' //修改自定义data-**的属性
-
修改事件处理函数
div.onclick默认null,但是如果改为一个函数,那么在点击的时候浏览器会调用这个函数调用是通过fn.call(div,event)
-
修改文本内容
div.innerText = 'xxx' div.textContent = 'xxx' -
修改HTML内容
div.innerHTML = '<strong>重要内容</strong>' -
修改标签
div.innerHTML = '' //先清空 div.appendChild(div2)//再加内容 -
修改父节点
newParent.appendChild(div)
4.4查看节点
-
查看父节点
node.parentNode //node.parentElement -
查看父节点的父节点
node.parentNode.parentNode -
查子字节
node.childNodes//node.children,优先使用- 当子节点变化时,两者也会同时变化
-
查兄弟节点
node.parentNode.childNodes //node.parentNode.children,还要排除自己 let siblings = [] let c2 = div2.parentElement.children for(let i = 0;i<c2.length;i++){ if(c2[i] !== div2){ siblings.push(c[i]) } } -
查看第一个子节点/最后一个子节点
node.firstChild node.lastChild -
查看上一个兄弟节点/下一个兄弟节点
node.previousSibling node.nextSibling -
遍历一个div的所有元素
travel = (node, fn) => { fn(node) if(node.children){ for(let i=0;i<node.children.length;i++){ travel(node.children[i], fn) } } } travel(div1, (node) => console.log(node))
五、DOM操作跨线程
5.1JS引擎渲染引擎
浏览器分为渲染引擎和JS引擎,两者各司其职,渲染引擎只能操作页面,JS引擎只能操作JS
document.body.appendChild(div1) //这句话如何改变页面
- 当浏览器发现JS在body里面加了一个div1对象,会通知渲染引擎在页面里也增加一个div元素
- 新增的div元素所有属性照抄div1对象
- 对div1的多次操作,浏览器可能会合并成一次操作,也可能不会
-
对div1的标准属性(id、className、title)或者
data-**属性修改,会被浏览器同步到页面中 -
对div1的非标准属性修改,会停留在JS线程中,不会同步到页面中
-
如果有自定义属性,又想被同步到页面中,请使用
data-作为前缀
5.2Property和Attribute
JS线程中的div1所有属性叫做property;渲染引擎中的div1对应标签的属性,叫做attribute
- 大部分时候,两者相等
- 如果不是标准属性,它们只会在一开始相等,attribute只支持字符串,property支持字符串、布尔类型