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介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!