# DOM编程
# 获取元素
window.id
或者直接id
querySelector('red')
querySelectorAll('red')[0]
document.documentElement
可以获取整个html元素
TIP
一般在兼容IE才会用getElementById
, getElementsByTagName
这些API
# 元素的原型
# 节点与元素
元素(Element, 也叫标签(Tag))节点(Node)的一种, 文本(Text)是另一种节点, Node
对象有一个nodeType
方法可以判断这个节点属于哪种类型:
// 最常用的节点类型如下
Element.nodeType = 1
Text.nodeType = 3
Comment.nodeType = 8
2
3
4
5
# DOM增删改查: CRUD boy 的宿命
# 增
# 创建标签节点
let div = document.createElement('div') //在JS线程里存在, 还没有通知渲染引擎将 div 渲染到屏幕上
document.body.appendChild(div) //将div挂载到body上, 现在能够显示在屏幕上
# 创建文本节点
let text = document.createTextNode('你好')
document.body.appendChild(text)
或者
document.body.innerText/textContent = '你好'
TIP
将同一个div
append到不用的父元素里, div
会添加到最后append的地方
# 删
删除元素有两种方法:
ParentNode.removeChild(ChildNode)
ChildNode.remove()
这两个方法都是将元素从DOM树上删除, 但没有在JS内存种删除, 如果事先使用一个变量存储这个节点, 那么可以用这个变量将删除的元素重新加载到DOM树上.
# 改
# 改属性
- 改
class
属性:div.className = 'red'
- 改
style
:div.style.backgroundColor = 'blue'
- 改
data-*
属性:div.dataset.x = 'xxx'
TIP
读取属性: div.getAttribute('color')
# 改事件处理函数
div.onclick
在原型链上被默认设置为null
, 如果将其改写为一个函数, 那么它将以fn.call(this, event)
方式调用, this
指向触发点击事件的元素, event
是包含点击事件的信息
# 改父元素
newParentNode.appendChild(div)
# 查
# 查父元素
div.parentNode
或者 div.parentElement
# 查爷爷
node.parentNode.parentNode
# 查子代
node.childNodes 或者 node.children
# 查兄弟姐妹
node.parentNode.childNodes
或者 node.parentNode.children
# 查看老大
node.firstChild
# 查看老幺
node.lastChild
# 查看哥哥
node.previousSibling
或者 node.previousElementSibling
# 查看弟弟
node.nextSibling
或者 node.nextElementSibling
# DOM cross thread
浏览器里有渲染引擎和JS引擎, 它们是两个模块, 各自独立工作. JS引擎不能去操作页面, 那么我们是怎么用DOM来改变页面的呢? 是因为JS引擎对DOM操作后, 浏览器会通知渲染引擎按照JS里执行的代码去重新渲染页面. 这算是一种跨线程通信. 而这通信成本使得DOM操作的速度受到影响.
# 属性同步
对元素的属性的修改(指在JS代码里)有可能同步到渲染引擎里. 标准属性与 data-*
属性 会同步(href
, id
, class
, title
, data-x
等), 而自定义属性不会同步. 如果想让自定义属性也能同步, 则应使用 data-
属性
# Property 与 Attribute
JS线程里div的属性叫Property, 渲染引擎里div的属性叫Attribute. 大部分时两者相同, 如果不是标准属性, 那么修改后就会不同了.
TIP
attribute只支持字符串, property支持字符串和布尔等类型