DOM 简介
网页其实是一棵树
JS如何操作这棵树
浏览器往window上加一个document即可,JS用document操作网页,这就是Document Object Model 文档对象模型。
API
获取元素,也叫标签
有很多API
window.idxxx //或直接 idxxx,最简单的方法,但有时会有冲突
document.getElementByld('idxxx')
document.getElementsByTagName('div')[0]
document.getElementsByClassName('red')[0]//这三种方法复杂不常用
document.querySelector('#idxxx') //注意加#号
document.querySelectorAll('.red')[0]//这两种方法是常用的
获取特定元素
获取html元素
document.ducumentElement
获取head元素
document.head
获取body元素
document.body
获取窗口(窗口不是元素)
window
获取所有元素
document.all
document.all
是ie发明的,是第6个falsy值。
元素的6层原型链
我们获取到的元素是一个对象,所以需要搞清楚它的原型。
console.dir(div1)看原型链——
第一层原型
HTMLDivElement.prototype
,这里面是所有div共有的属性。
第二层原型
HTMLElement.prototype
,这里面是所有HTML标签共有的属性。
第三层原型
Element.prototype
,这里面是所有XML、HTML标签的共有属性(浏览器不止展示HTML)
第四层原型
Node.prototype
,这里面是所有节点的共有属性,节点包括XML标签文本注释、HTML标签文本注释等等。
第五层原型
EventTarget.prototype
,里面最重要的函数属性是addEvenListener
第六层原型
Object.prototype
节点
节点和元素的区别
Node?Element?
节点Node包括以下几种,其中就包括Element
MDN有完整描述,x.nodeType
得到一个数字。
节点的增删改查
增
-
创建一个标签节点
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.appenChild('你好')
-
插入页面中
创建的标签默认处于JS线程中,必须把它插到head后者body里面,它才会生效。
document.body.appendChild(div)
或者
已在页面中的元素.appendChild(div)
删
-
两种方法
旧方法:
parentNode.removeChild(childNode)
新方法:
childNode.remove()
//ie不支持 -
思考
如果一个node被移出页面(DOM树),那么它还能再次返回页面中吗?
可以。
怎样删除node呢?
div = null
改
-
改属性
-
改标准属性
-
改id
div1.id = 'div1'
-
改class
//class是JS保留字,不能直接用div1.class div1.className = 'blue' //会全覆盖,想再添加只能 div1.className += ' red' div1.classList.add('green') //class = "blue red green"
-
改style
div1.style = 'width: 100px; color: blue;' div1.style.width = '200px' //改style的一部分
当改动类似于
background-color
这种有中划线的属性时,改写为div1.style.backgroundColor
就可以执行。 -
改data-* 属性
div1.dataset.x='river'
-
-
读标准属性
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
的升级版
-
-
改内容
-
改文本内容
div.innerText = 'xxx' div.textContent = 'xxx' //两者几乎没有区别
-
改HTML内容
div.innerHTML = '<strong>重要内容</strong>'
-
改标签
div.innerHTML = '' //空字符串,先清空 div.appendChild(div2) //再改内容
-
-
改爸爸
newParent.appendChild(div)
查
-
查爸爸
node.parentNode 或 node.parentElement
-
查爷爷
node.parentNode.parentNode
-
查子代
node.childNodes 或者 node.children
-
第一个问题:
下面
console.log(test.childNodes.length)
打印结果为7,依次为text,li,text,li,text,li,text。text是回车+空格
因此下面这个打印结果就是3
用children就可以避免这种情况,多用children!!
-
第二个问题:
当子代变化时,两者也会实时变化吗?
会实时变化。
而
document.querySelectorAll('li')
就不会实时变化
-
-
查兄弟姐妹
node.parentNode.childNodes //还要排除自己 node.parentNode.children //还要排除自己
也就是要做两件事情,第一件是上面的找到parent的孩子,第二件就是遍历这个数组并且排除自己。
操作示例:
div1的parent共有35个孩子
通过遍历并排除掉div1自己,得到自己的兄弟姐妹数组siblings
-
查看老大
node.firstChild
-
查看老幺
node.lastChild
-
查看上一个哥哥/姐姐
node.previousSibling //有可能会查看到文本节点 node.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(div1,(node) => console.log(node))
DOM 操作是跨线程的
浏览器功能分为渲染引擎和JS引擎,渲染引擎用来渲染HTML和CSS,JS引擎来操作JS。
跨线程操作
各线程各司其职
JS引擎不能操作页面,只能操作JS
渲染引擎不能操作JS,只能操作页面
那document.body.appendChild(div1)
这句话是如何改变页面的呢?
跨线程通信
当浏览器发现JS在body里面加了个div1
对象
浏览器就会通知渲染引擎在页面里也新增一个div
元素
新增的div
元素所有属性都照抄div1
对象
注意:一个是对象,一个是元素。
插入新标签的完整过程
在div1放入页面之前
对div1所有的操作都属于JS线程内的操作
把div1放入页面之时
浏览器发现JS的意图,就会通知渲染线程在页面中渲染div1对应的元素
把div1放入页面之后
你对div1的操作都有可能会触发重新渲染
div1.id='newId'
可能会重新渲染,也可能不会
div1.title='new'
可能会重新渲染,也可能不会
如果连续对div1多次操作,浏览器可能会合并成一次操作,也可能不会,就比如下面这个例子,如果不加test.clientWidth
,那JS就会默认合并导致动画无法显示。
属性同步
标准属性
对div1的标准属性修改,会被浏览器同步到页面中
比如id、className、title等
data-* 属性
同上
非标准属性
对非标准属性的修改,则只会停留在JS线程中,不会同步到页面里
比如x属性,示例代码
启示
如果你有自定义属性,又想被同步到页面中,请使用data-
作为前缀
Property V.S. Attribute
property 属性
JS线程中div1的所有属性,叫做div1的property
attribute属性
渲染引擎中div1对应标签的属性,叫做attribute
区别
大部分时候,同名的property 和 attribute 值相等
但如果不是标准属性,那么它俩只会在一开始时相等
但注意attribute只支持字符串
而property支持字符串、布尔等类型
什么叫封装
举例
电脑笔记本就是CPU、内存、硬盘、主板、显卡的封装,用户只需要接触显示器、键盘、鼠标、触控板等设备,即可操作复杂的计算机。
接口
被封装的东西需要暴露一些功能给外部,这些功能就是接口,如USB接口、HDMI接口。
设备只要支持这些接口,即可与被封装的东西通讯,比如键盘、鼠标支持USB接口,显示器支持HDMI接口。
术语
库
我们把提供给其他人用的工具代码叫做库,比如JQuery、Underscore
API
库暴露出来的函数或属性就叫做API(应用编程接口)
框架
当库变得很大,并且需要学习才能看懂,那么这个库就是框架,比如Vue 、React
DOM封装
源码
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!