JS编程接口之DOM

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、title

  • data- x属性
    同标准属性

  • 非标准属性
    对非标准属性的修改,则只会停留在JS线程中
    不会同步到页面里
    比如x属性(x=‘test’;div.x='更该内容')

注意:如果有自定义属性,又想被同步到页面中,建议使用data-作为前缀

4.4 Property和Attribute

  • Property属性
    JS线程中div1的所有属性,叫做div1的Property

  • Attribute属性
    渲染引擎中div1对应标签的属性,叫做attribute

  • 区别
    大部分时候,同名的property和attribute值相等
    但如果不是标准属性,那么他两只会在一开始时相等
    注意attribute只支持字符串
    property支持字符串、布尔等类型

部分资料来源:饥人谷

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容