网页其实就是一棵树
那么JS是如何操作这棵树的呢?
浏览器往window上加一个document就可以,JS用document操作网页,这就是Document Object Model文档对象模型
DOM操作很难用,而且很反人类
获取元素,也叫做标签,有很多API
http://window.xxx或者直接 xxx
![9b42288833bda16dcb87fd57ed32e65a.png](https://i-blog.csdnimg.cn/blog_migrate/19fa073ce959dc61fd92cc17d5cce28f.jpeg)
document.getElementById("s_tab") // 抓取id
![cd9124f00332c2e94d1b76a66c50bd1e.png](https://i-blog.csdnimg.cn/blog_migrate/11f93ca4143584c36c93101ac1f1efbe.jpeg)
document.getElementsByClassName('s_tab_inner')[0] // 抓取类名,返回的结果是个数组,所以要通过下标来取值
![2c84945831d5250664cf652c8379f27e.png](https://i-blog.csdnimg.cn/blog_migrate/3126f71e1ba066452dca57858b6e4df6.jpeg)
document.getElementsByTagName('div')[0] // 抓取标签名
![9ae66df9298f4f6678f4bafe57500765.png](https://i-blog.csdnimg.cn/blog_migrate/949b005cc6aae4b5f34a7e2c59aa80ff.png)
document.querySelector('#s_tab') // 查询选择器
![9b116ee227e944a05f5753a02d9c6d7b.png](https://i-blog.csdnimg.cn/blog_migrate/597bd3b3d13c3ee3196ff8599b06d972.jpeg)
document.querySelectorAll(".s_tab_inner")[0] // 查询所有选择器,选取第0个
![c7f8ac8fa61aeeb47706d852ca953c18.png](https://i-blog.csdnimg.cn/blog_migrate/cf9b7ab4d46751e7e5dc929978f699af.jpeg)
在实际工作中常用的就是后两个,自己做小demo时可以直接用(例如:idCards),只有要兼容IE的时候才用其他的(据说IE要采用谷歌浏览器内核了,以后大家就不用头疼兼容IE了)
上面是常用操作,获取元素
下面获取特定元素:
获取html元素
document.documentElement
![187a8eb1b891af9389c23cb1ddf80ece.png](https://i-blog.csdnimg.cn/blog_migrate/69db05505bdd0c3f276b61fc45a9564d.png)
获取head元素
document.head
![d127146da24ba937fe98979b4d0c8a1e.png](https://i-blog.csdnimg.cn/blog_migrate/f6adeb86e986aa193c3b159c980a7627.jpeg)
获取body元素
document.body
![f0607ed2152b99b9cea96139c491eb82.png](https://i-blog.csdnimg.cn/blog_migrate/3f78ee41ca0719a0134ac7eb5e7b8927.jpeg)
获取窗口(窗口不是元素),但是也能获取到当前窗口。虽然window不是一个标签,但是我们有的时候也会获取到它添加一些全局的事件监听。
window
![b5ba63ef5f4d327d00a47795cdcae73e.png](https://i-blog.csdnimg.cn/blog_migrate/1086d30517477e5cdceababaf37744fd.png)
获取所有元素,这个标签出自IE
document.all
这个document.all 是个奇葩,第六个falsy值
![8c2da66122f40f1e2caee52218aad77a.png](https://i-blog.csdnimg.cn/blog_migrate/7cef009a30caccbba3ac0ed3d66cdbef.jpeg)
获取到的元素显然是个对象
那么就抓取一个div对象看一下,console.dir(div2)看一下原型链
第一层原型HTMLDivElement,这里面时所有div共有的属性,
第二层原型HTMLElement,这里面是所有HTML标签共有的属性,
第三层原型Element.prototype,这里面是所有HTML,XML标签的共有属性,
第四层原型Node.prototype,这里面是所有节点共有的属性,节点包括XML标签文本注释、HTML标签文本注释等,
第五层原型EventTarget.prototype,这里面最重要的函数属性是addEventListener,
最后一层原型就是Object.prototype
节点、元素、标签关系:
节点包括元素和文本等,元素就是标签,叫法不同而已
节点Node包括以下几种:
在此引用MDN,更加直白
Node.nodeTypedeveloper.mozilla.org![24afd1956607e4346abe662aef81c266.png](https://i-blog.csdnimg.cn/blog_migrate/aa3509e0251c81639547c62dbc8a734c.jpeg)
下面就要说到节点的增删改查,程序员的基本操作,不管前端还是后端都要会
1.增
创建一个标签节点
let div1 = document.createElement('div')
document.createElement('style')
document.createElement('div')
创建一个文本节点
text = document.craeteTextNode('hello')
标签里面插入文本
div1.appendChild(text)
div1.innerText = 'hello'
或者
div1.textContent = 'hello'
但是不能用div1.appendChild('hello') //因为它是文本
插入页面中
创建的标签默认在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中了,因为一个元素不能出现在两个地方,除非复制
删除
有两种方法:
老方法:parentNode.childChild(childNode)
新方法: childNode.remove()
改
写标准属性
改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 ' //background-color 替换成大小写格式 backgroundColor
改data-* 属性 : div.dataset.x = 'rank' //用于嵌入自定义属性,h5新增的属性,主要分为2部分:1.属性名不要包含到小写,在data-后必须至少有一个字符。2.该属性可以是任何字符串
读标准属性
div.classList/a.href
div.getAttribute('class') / a.getAttribute('href')
两种方法都可以,但值可能稍微有些不同
改事件处理函数
div.onclick 默认为null
默认点击div不会有任何事件触发
但是如果把div.onclick改为一个函数fn
那么点击div的时候,浏览器就会调用这个函数
这里div就会被当作this
event则包含了点击事件的所有信息
改内容
修改文本内容
div.innerText = 'xxx' //兼容IE,是IE发明的
div.textCountent = '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
查兄弟姐妹
node.parentNode.childNodes 还要排除自己
node.parentNode.children 也要排除自己
查询大儿子
node.firstChild
查询最小的儿子
node.lastChild
查询上一个兄弟
node.previousSibling
查询下一个兄弟
node.nextSibling
DOM操作为什么慢,那是因为他是跨线程了,浏览器分为渲染引擎和JS引擎
线程都是各司其职,JS引擎不能操作页面,只能操作JS,同样渲染引擎不能操作JS,只能操作页面
![40835d96784291eb576912865ccfee4b.png](https://i-blog.csdnimg.cn/blog_migrate/5b28f7272f15d43bee5d31ec8d9c3356.jpeg)
下面举个例子:
document.body.appendChild(div1)
当浏览器发现JS在body里面加了一个div1对象,浏览器就会通知渲染引擎在页面中新增一个div元素,新增的div元素所有属性都照抄div1对象