DOM编程
网页其实是一棵树
JS如何操作这棵树?
浏览器往window上加一个document即可
JS用document操作网页,这就是Document Object Model文档对象模型
记住一个事实,DOM很难用
获取元素,也叫标签
- 有很多API
window.idxxx或者直接idxxx
document.getElementByid('idxxx')
document.getElementsByTagName('div')[0]
document.getElementsByClassName('red')[0]
document.querySelector('#idxxx')
document.querySelectorAll('.red')[0]
-
用哪一个
工作中使用
querySelector和querySelectorAll做demo直接用
idxxx要兼容IE的可怜虫才用
getElement(s)Byxxx
获取特定元素
-
获取html元素
document.documentElement -
获取head元素
document.head -
获取body元素
document.body -
获取窗口(窗口不是元素)
window -
获取所有元素
document.all这个
document.all是个奇葩,第六个falsy值
什么是节点(和元素的区别)
-
节点Node包括以下几种
1、表示元素Element,也叫标签Tag
3、表示文本Text
8、表示注释 Comment
9、表示文档 Document
11、表示文档片段 DocumentFragment
记住 1 和 2 即可
节点的增删改查
增
- 创建一个标签节点
let div1=document.creatElement('div')
document.createElement('style')
document.createElement('script')
document.createElement('li')
- 创建一个文本节点
text1 = document.createTextNode('你好')
- 标签里面插入文本
div1.appendChild(text1)
div1.innerText='你好'或者div1.textContent='你好'
//但是不能用div1.appendChild('你好')
-
插入页面
你创建的标签默认处在JS线程中,你必须把它插到head或者body里面,它才会生效
document.body.appendChild(div)或者
已再页面中的元素
.appendChild(div)
appendChild
页面中有div#test1和div#test2
let div = document.createElement('div')
test1.appendChild(div)
test2.appendChild(div)
请问最终div出现在哪里?
test2里 一个元素不能出现在两个地方,除非复制一份 .cloneNode
删
- 两种方法
旧方法:parentNode.removeChild(node)
新方法:childNode.remove()
-
思考
如果一个node被移出页面(DOM树)
那么它还可以再次回到页面中么?
可以的,它还在内存里
改
-
改写标准
改class:
div.className='red blue'(全覆盖)改class:
div.classList.add('red')改style:
div.style='width:100px;color:blue;'改style的一部分:
div.style.width='200px'大小写:
div.style.backgroundColor='white'改data-*属性:
div.dataset.x='frank' -
读标准属性
div.classList/a.hrefdiv.getAttribute('class')/a.getAttribute('href')两种方法都可以,但值可能稍微有些不同
改事件处理函数
-
div.onclick 默认为null
默认点击div不会有任何事情发生,但是如果你把div.onclick改为一个函数fn
那么点击div的时候,浏览器就会调用这个函数,并且是这样调用的fn.call(div.event)
div会被当作this,event则包含了点击事件的所有信息,如坐标
-
div.addEventListener
是div.onclick的升级版
改内容
-
改文本内容
div.innerText='xxx'div.textContent='xxx'两者几乎没有区别
-
改HTML内容
div.innerHtml='<strong>重要内容</strong>' -
改标签
div.innerHTML=''//先清空div.appendChild(div2)//再加内容
查
- 查爸爸
node.parentNode或者node.parentElement
- 查爷爷
node.parentNode.parentNode
- 查子代
node.childNode或者node.children
思考:当子代变化时,长度会发生变化么
- 查兄弟姐妹
node.parentNode.childNodes还要排除自己
node.parentNode.children还要排除自己
- 查老大
node.firstChild
- 查看老幺
node.lastChild
- 查看上一个哥哥/姐姐
node.previouSibling
- 查看下一个弟弟/妹妹
node.nextSibling
DOM操作是跨线程的
浏览器分为渲染引擎和JS引擎
-
各个线程各司其职
JS引擎不能操作页面,只能操作JS,渲染引擎不能操作JS,只能操作页面
document.body.appendChild(div1)这句JS是如何改变页面的 -
跨线程通信
当浏览器发现JS在body里面加了个div1元素,浏览器就会通知渲染引擎在页面里也新增一个div元素
新增的div元素所有属性都照搬div1对象
插入新标签的完整过程
-
在div1放入页面之前
你对div1所有的操作都属于JS线程内的操作
-
把div1放入页面之时
浏览器会发现JS的意图
就会通知渲染线程在页面中渲染div1对应的元素
-
把div1放入页面之后
你对div1的操作都有可能会触发重新渲染
div1.id='newld'可能会重新渲染,也可能不会div1.title='new'可能会重新渲染,也可能不会如果你连续对div1多次操作,浏览器可能会合并成一次操作,也可能不会
属性同步
-
标准属性
对div1的标准属性的修改,会被浏览器同步到页面中
比如id、className、title等
-
data-*属性
同上
-
非标准属性
对非标准属性的修改,则只会停留在JS线程中
不会同步到页面里
比如x属性
-
启示
如果你有自定义属性,又想被同步到页面中,请使用data-作为前缀
\