1 获取元素API
- 通过id获取元素
// 方法1
window.id
// 方法2
id
// 方法3
document.getElementById('id')
- 通过标签获取元素
document.getElementsByTagName('div')[0]
- 通过类名获取元素
document.getElementsByClassName('red')[0]
- 通过querySelector获取元素
// 语法
document.querySelector('#id')
// 实例:需要找到div下作为第二个儿子的span
document.querySelector('div>span:nth-child(2)')
- 通过querySelectorAll获取元素
// 语法
document.querySelectorAll('.red')[0]
// 实例:找到满足条件的所有span,然后使用第 i 个
document.querySelectorAll('div>span:nth-child(2)')[i]
2 元素的六层原型链

div完整原型链(自身属性和共有属性)

console.dir(div1)查看原型链
3 节点的增删改查
3.1 节点的增(创建)
- 创建一个标签节点
// 添加div节点
let div1 = document.createElement('div')
// 添加style节点
document.createElement('style')
// 添加script节点
document.createElement('script')
// 添加li节点
document.createElement('li')
- 创建一个文本节点
text1 = document.createTextNode('你好')
- 在标签里面插入文本
// 方法1
div1.appendChild(text1)
// 方法2
div1.innerText = '你好'
// 方法3
div1.textContent ='你好'
- 将创建内容插入页面
// 创建的标签默认处于JS线程中,必须将其插入head或body里才会生效
document.body.appendChild(div1)
已在页面中的元素.appendChild(div1)
注意:关于append的小知识
- 页面中存在div#test1 和div#test2
- 运行代码,最终div会出现在test2中,因为一个元素不能出现在两个地方
let div1 = document.createElement('div')
test1.appendChild(div1)
test2.appendChild(div1)
- 解决方法:将元素复制一份,再进行添加
// cloneNode内参数是false为浅拷贝,只拷贝节点本身
// 参数是true为深拷贝,连同子节点一起拷贝
div2 = div1.cloneNode(ture)
// 将div1添加至head
document.head.appendChild(div1)
// 将div2添加至body
document.body.appendChild(div1)
3.2 节点的删除
方法1(旧方法)
- 寻找父节点,通过父节点进行删除
// 语法
parentNode.removeChild(childNode)
// 实例,删除div1
div1.parentNode.removeChild(div1)
方法2(新方法)
- 直接删除节点
childNode.remove()
3.3 属性修改
3.3.1 写标准属性
- 改id
div.id = 'div2'
- 改class
// 添加的class会将前面的覆盖
div.className = 'red'
// class添加导致覆盖的解决方法,运行后div的class为red blue
div.classList.add('blue')
- 改style
// 直接修改,但会覆盖先前的style,所以不建议使用
div.style = 'width:100px;color:blue'
// 针对性修改style的一部分,建议使用
div.style.修改属性= '修改内容'
- data-*属性
// 为div添加一个data-x属性,内容为test
div.setAttribute('data-x','test')
// 获取data-x内容的方法
// 方法1
div.getAttribute('data-x')
// 方法2
div.dataset.x
//修改data-x属性,将data-x的内容修改覆盖为sherry
div.dataset.x = 'sherry'
3.3.2 读标准属性
- 读一般属性
div.属性名
- 读链接
直接使用id.href读取,有可能浏览器会对网址进行加工,补全http/https等部分,可以通过以下方法获取原本值
// 方法1
div.classList/a.href
// 方法2
div.getAttribute('class')/a.getAttribute('href')
3.4 查看元素API
- 查父亲
// 方法1
node.parentNode
// 方法2
node.parentElement
- 查爷爷
ndoe.parentNode.parentNode
- 查子代(优先使用children)
// 方法1
node.childNodes
// 方法2
node.children
- 查兄弟姐妹(优先使用children)
// 方法1,需要排除自己
ndoe.parentNode.childNodes
//方法2,需要排除自己
ndoe.parentNode.children
// 排除自己的方法,sibling就是查找的包含兄弟姐妹的数组
let siblings = []
let c = div.parentElement.children
for (let i = 0; i < c.length; i++) {
if (c[i] !== div) {
siblings.push(c[i])
}
}
- 查看第一个儿子
// 方法1
node.firstChid
// 方法2
node.children[0]
- 查看最后一个儿子
node.lastChild
- 查看上一个哥哥/姐姐
// 可能查到文本节点
ndoe.previousSibling
// 如果想避查到文本节点
ndoe.previousElementSibling
- 查看下一个弟弟/妹妹
// 可能查到文本节点
node.nextSibling
// 如果想避查到文本节点
node.nextElementSibling
- 查看(遍历)一个div里的所有元素
travel = (node, fn) => {
fn(node)
if (node.children) {
for (let i = 0; i < node.children.length; i++) {
travel(node.children[i],fn)
}
}
}
travel(div, (node) => {
console.log(node)
})
4 DOM操作跨线程
4.1 操作过程
-
各线程各司其职
JS引擎不能操作页面,只能操作JS
渲染引擎不能操作JS,只能操作页面
document.body.appendChild(div1)如何改变页面 -
跨线程通信
当浏览器发现JS在body内加了个div1对象
浏览器会通知渲染引擎在页面也新增一个div元素
新增的div元素所有属性都照抄div1对象
4.2 插入新标签的完整过程
div1放入页面之前
对div1所有的操作都属于JS线程内的操作div1放入页面之时
浏览器会发现JS的意图
就会通知渲染线程在页面中渲染div1对应的元素div1放入页面之后
对div1的所有操作都有可能触发重新渲染
div1.id = ‘newId’可能重新渲染(如id有css样式),也可能不会
div.title = ‘new’可能会重新渲染(如通过伪元素修改div的title),也可能不会
如果连续对div1多次操作,浏览器可能会合并成一次操作,也可能不会
// 实例
// html代码
<div id="test"></div>
// css代码
.start{
border:1px solid red;
width:100px;
height:100px;
transition:width 1s;
}
.end{
width:200px;
}
// js代码
test.classList.add('start')
// 如果不添加这句话,不需要在此读取高度
// add('start')和add('end')则会被合并成一次操作,从而导致动画不生效
// 添加后触发重新渲染
test.clientWidth
test.classList.add('end')
4.3 属性同步
标准属性
对div1的标准属性的修改,会被浏览器同步到页面中
比如id、calssName、titledata- x属性
同标准属性非标准属性
对非标准属性的修改,则只会停留在JS线程中
不会同步到页面里
比如x属性(x=‘test’;div.x='更该内容')
注意:如果有自定义属性,又想被同步到页面中,建议使用data-作为前缀
4.4 Property和Attribute
Property属性
JS线程中div1的所有属性,叫做div1的PropertyAttribute属性
渲染引擎中div1对应标签的属性,叫做attribute区别
大部分时候,同名的property和attribute值相等
但如果不是标准属性,那么他两只会在一开始时相等
注意attribute只支持字符串
property支持字符串、布尔等类型
部分资料来源:饥人谷