什么是DOM
Document Object Model文档对象模型(JS用document操作网页)
什么是API
Application Programming Interface应用程序接口,是一些预先定义的接口(函数,HTTP接口)
获取任意元素(element)、标签(tag)API
window.idxxx//或者直接idxxx(可以做demo时偷偷用)
document.getElementById('idxxx')
document.getElementsByTagName('div')[0] //注意Element[s]
document.getElementsByClassName('red')[0]
document.querySelector('#idxxx') //工作用
document.querySelectorAll('.red')[0] //工作用
获取特定元素(element)
- 获取html元素
document.documentElement
- 获取head元素
document.head
- 获取body元素
document.body
- 获取窗口(窗口不是元素)
window
- 获取所有元素
document.all //这个是个奇葩,第六个falsy值
获取的元素显然是个对象,那么对象的原型呢?
元素的六层原型链
console.dir(div1)//查看div原型链
Chrome会有显示错误
自身属性:className、id、style等等
第一层原型HTMLDivElement.prototype:这是所有div共有的属性
第二层原型HTMLElement.prototype:这是所有HTML标签共有的属性
第三层原型Element.prototype:这是所有XML、HTML标签共有的属性
第四层原型Node.prototype:这是所有节点共有的属性,包括XML标签文本注释、HTML标签文本注释等等
第五层原型EventTarget.prototype:里面最重要的函数属性是addEventListener
第六层原型Object.prototype
节点和元素分不清楚
- x.nodeType得到一个数字
- 1表示文本元素Element,也叫做标签Tag
- 3表示文本Text
- 8表示注释Comment
- 9表示文档Document
- 11表示文档片段DocumentFragment
记住1、3即可
节点的增删改查
增
创建一个标签节点
let div1 = document.createElement('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中,一个元素不能出现在两个地方,除非复制一份node.cloneNode
删
parentNode.childChild(childNode)//旧方法
childNode.remove()//新方法
如果一个node被移除页面(DOM树)那么他还可以再次回到页面中吗?
div2.remove() //IE可能不兼容
document.body.appendChild(div2) //又加回来了,可见在内存中没有删除
改
改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'
改date属性
div.dateset.x = 'frank'
正常/特殊的读属性
(特殊)若使用
console.log(test.href)//这里是个相对路径的a标签,那么就会错误地显示 http://当前网址/xxx
需要使用
div.classList//特殊用a.href
div.getAttribute('class')//特殊用a.getAttribute('href')
这两种方法都可,但是值可能稍有不同
改事件处理函数
div.onclick
默认为null,默认点击div不会发生任何事,但是如果把div.onclick
改为一个函数fn,那么点击div的时候,浏览器就会调用这个函数,并且是这样调用的fn.call(div,event)
,div会被当做this,event则包含了点击事件的所有信息(如:坐标)
div.addEventListener
是div.onclick
的升级版,后面会说明
查
查爸爸
node.parentNode //或者 node.parentElement
查爷爷
node.parentNode.parentNode
查儿子
node.childNodes //或者 node.children
//若儿子发生变化,两者也会改变吗?会
node.firstChild//查看老大
node.lastChild//查看老小
查兄弟姐妹
node.parentNode.childNodes//还要排除自己
node.parentNode.children//还要排除自己
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跨线程
浏览器有渲染引擎和JS引擎
各线程各司其职。JS引擎不能操作页面只能操作JS;渲染引擎只能操作页面。
那么
document.body.appendChild(div1)
这句JS是如何改变页面的呢?
跨线程通讯
当浏览器发现JS在body里面加了div1对象,就会通知渲染引擎在页面里也新增一个div元素,新增的div元素所有属性都照抄div1对象
在div1放入页面之前,所有的操作都在JS引擎内
在div1放进页面之时,浏览器通知渲染引擎在页面中渲染div1对应元素
在div1放在页面之后,对div1的操作都会有可能触发重新渲染
标准属性(id、className、title等)和date-会同步,非标准属性不会同步
property和Attribute
JS线程中的所有属性叫做 div1的property
渲染引擎中div1对应标签的属性叫做 Attribute
区别
- 大部分时候,同名的property和attribute值相同,但如果不是标准属性,那么相等只会在最开始存在
- attribute只支持字符串
- property支持字符串、布尔类型等