第9天-BOM和DOM
什么是DOM
文档对象模型(Document Object Model),DOM作用:可以去修改网页内容、样式、结构。 每个浏览器都会把html文档解析成dom树,就可以用相关方法和属性操作网页元素
DOM节点
什么是节点?节点之间的关系?
- 根节点:html, 也叫祖先节点
- 父节点
- 子节点
- 兄弟节点
节点类型
元素节点 | 1 |
文本节点 | 3 |
文档节点 | 9 |
注释节点 | 8 |
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id='box'>heboan</div> <div id='box2'><!--这是注释--></div> <script> oBox = document.getElementById('box') console.log(oBox.nodeType) //1 元素节点 console.log(oBox.firstChild.nodeType) //3 oBox的第一个子节点是heboan,这是个文本节点 console.log(document.nodeType) //9 文档节点 oBox2 = document.getElementById('box2') console.log(oBox2.firstChild.nodeType) //8 注释节点 </script>
节点类型使用场景
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul id='ul1'> <li>1111</li> <li>2222</li> <li>3333</li> </ul> <script> //需求,点击document,修改li的背景色 var oUl1 = document.getElementById('ul1'); //通过节点的方式找li,childNodes返会所有子节点 var aNodes = oUl1.childNodes document.onclick = function(){ for(var i=0;i<aNodes.length;i++){ aNodes[i].style.backgroundColor = "red" } } </script>
这行上面代码是会报错的,这是为什么呢?
我们console.log(aNodes)看看,发现有7个对象,我们不是只有3个li吗???
这是因为,它识别到空格为text了
所以,这个时候,我们就可以利用节点类型进行过滤了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> //需求,点击document,修改li的背景色 var oUl1 = document.getElementById('ul1'); //通过节点的方式找li,childNodes返会所有子节点 var aNodes = oUl1.childNodes console.log(aNodes) document.onclick = function(){ for(var i=0;i<aNodes.length;i++){ if(aNodes[i].nodeType == 1){ //判断节点类型 aNodes[i].style.backgroundColor = "red" } } } </script>
节点名的使用场景
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul id='ul1'></ul> <input id='ipt' /> <button id="btn">按钮</button> <script> var oUl = document.getElementById('ul1'); var oIpt = document.getElementById('ipt'); var oBtn = document.getElementById('btn'); oBtn.onclick = function(){ //创建一个li对象 var oLi = document.createElement('li'); oLi.innerHTML = oIpt.value; oUl.appendChild(oLi); } //点击新添加的li有背景变化 oUl.onclick = function(ev){ //当我们点击的事li才设置颜色,如果点击的是ul就不做操作 if(ev.target.nodeName === 'LI'){ ev.target.style.backgroundColor = "#009F95"; } } </script>
上面的代码的如果不做nodeName判断,那么就会出现bug,点击到ul,会导致整个ul变色
查找元素方法
getElement系列
getElementById :id来获取
getElementsByClassName: 通过类名称来获取
getElementsByTagName: 通过标签名来获取
总结:凡是Element带s,就表示返回的事一个集合
通过设置范围,查找相应的元素
document.getElementById
obj.getElementById
querySelector系列
查找 wrap下面的所有的div
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> var oWrap = document.getElementById('wrap') var aDiv = oWrap.getElementsByTagName('div') console.log(aDiv) </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> var oDiv = document.querySelectorAll('#wrap div') console.log(oDiv) </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> var oBox = document.querySelector('#box') console.log(oBox) </script>
querySelectorAll返回有的符合条件的,querySelector只返回某一个
总结:两者的区别,getElement执行效率更高,查找起来相对麻烦些
常用的属性
childnodes 获取所有子节点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="wrap"> <div>111111</div> <div>222222</div> <div>333333</div> <div>444444</div> </div> <script> //根据方法获取节点 var oWrap = document.getElementById('wrap') //根据属性获取节点 console.log(oWrap.childNodes) //获取oWrap所有的子节点 </script>
可以看到所有子节点包含了空格(文本节点),如果只想获取所有的子元素节点,可以使用children
children 获取所有的子元素节点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="wrap"> <div>111111</div> <div>222222</div> <div>333333</div> <div>444444</div> </div> <script> //根据方法获取节点 var oWrap = document.getElementById('wrap') //根据属性获取节点 console.log(oWrap.children) //获取oWrap所有的子节点 </script>
parentNode获取父节点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="wrap"> <div>111111</div> <div id=box>222222</div> <div>333333</div> <div>444444</div> </div> <script> var oWrap = document.getElementById('wrap') console.log(oWrap.parentNode) //获取 oWrap的父节点 </script>
previousSibling获取上一个兄弟节点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="wrap"> <div>111111</div><div id=box>222222</div><div>333333</div><div>444444</div> </div> <script> var oBox = document.getElementById('box') console.log(oBox.previousSibling) //获取 oBox的上一个兄弟节点 </script>
nextSibling获取下一个兄弟节点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div id="wrap"> <div>111111</div><div id=box>222222</div><div>333333</div><div>444444</div> </div> <script> var oBox = document.getElementById('box') console.log(oBox.nextSibling) //获取 oBox的上一个兄弟节点 </script>
DOM操作
createElement 创建一个元素
appendChild 添加一个子元素在最后
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul id='uL1'></ul> <button id="btn">click</button> <script> var oUL1 = document.getElementById('uL1') var oBtn = document.getElementById('btn') oBtn.onclick = function(){ //创建一个li元素 var oLi = document.createElement('li') oLi.innerHTML = 'heboan' //把创建的li元素添加到ul中 oUL1.appendChild(oLi) } </script>
inertBefore 在一个元素钱插入元素
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul id='uL1'> <li>11111</li> <li id=l2>22222</li> <li>11111</li> </ul> <button id="btn">click</button> <script> var oUL1 = document.getElementById('uL1') var oBtn = document.getElementById('btn') var oL2 = document.getElementById('l2') oBtn.onclick = function(){ //创建一个li元素 var oLi = document.createElement('li') oLi.innerHTML = 'heboan' //在oL2元素前面插入oLi oUL1.insertBefore(oLi, oL2) } </script>
removeChild 删除一个子元素
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul id='uL1'> <li>11111</li> <li id=l2>22222</li> <li>11111</li> </ul> <button id="btn">click</button> <script> var oUL1 = document.getElementById('uL1') var oBtn = document.getElementById('btn') var oL2 = document.getElementById('l2') oBtn.onclick = function(){ //删除一个子元素 oUL1.removeChild(oL2) } </script>
宽、高和位置总结
鼠标位置:
- clientX/clientY 鼠标在浏览器可视区的坐标
- pageX/pageY: 鼠标在整个网页中的坐标
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body style="height: 3000px;"> <script> document.onclick = function(ev){ console.log(ev.clientX, ev.clientY) console.log('------------') console.log(ev.pageX, ev.pageY) } </script> </body>
offset系列
- offsetLeft offsetTop 是相对于定位父级的坐标位置
- offsetWidth offsetHeight 是元素实体所占的总宽高,例如:总宽度=内容 + padding +border
- offsetParent 表示定位的父级元素
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<style> #box{ width: 600px; height: 400px; border: 1px solid black; position: relative; margin: 100px auto; } #box-inner{ width: 50px; height: 60px; background-color: green; border: 5px solid deeppink; padding: 10px; position: absolute; left: 100px; top: 100px } </style> ... <body> <div id="box"> <div id=box-inner></div> </div> <script> var oBoxInner = document.getElementById('box-inner') document.onclick = function(){ //盒子的定位偏移量,是相对于定位父级的坐标位置 console.log("offsetLeft:" + oBoxInner.offsetLeft) //100 console.log("offsetTop:" + oBoxInner.offsetTop) //100 //offsetWidth表示盒子占的总宽度=border = width + padding console.log("offsetWidth:" + oBoxInner.offsetWidth) //80 //offsetHeight表示盒子占的总宽度=border = height + padding console.log("offsetHeight:" + oBoxInner.offsetHeight) //90 //offsetParent 表示定位的父级元素 console.log("offsetParent:" + oBoxInner.offsetParent.id) //打印出父级元素的id为 box } </script> </body>
scroll系列
- scrollLeft和scrollTop 表示元素滚出去的距离
- scrollWidth和scrollHeight 对象的实际内容的宽高,会随对象中内容超过可视区后而变大
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<style> #box{ width: 300px; height: 150px; border: 1px solid black; margin: 100px auto; padding: 10px; margin: 20px; /*表示溢出隐藏, 里面的盒子比这个盒子高,高的部分会被隐藏,从而出现滚动条*/ overflow: auto; } #box-inner{ width: 290px; height: 400px; background-color: orangered; margin: 0 auto; } </style> ... <body> <div id="box"> <div id=box-inner></div> </div> <script> var oBox = document.getElementById('box') document.onclick = function(){ //滚出去的距离 console.log("scrollTop: " + oBox.scrollTop) console.log("scrollLeft: " + oBox.scrollLeft) //内部实际占的宽度和高度 console.log("scrollWidth: " + oBox.scrollWidth) //303 console.log("scrollHeight: " + oBox.scrollHeight) //420 } </script> </body>
可视区宽高
- clientWidth
- clientHeight
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<style> #box{ width: 300px; height: 200px; border: 1px solid black; padding: 10px; } </style> ... <body> <div id="box"></div> <script> var oBox = document.getElementById('box') oBox.onclick = function(){ //可视区的宽高:包含width和padding console.log(this.clientWidth) //320 console.log(this.clientHeight) //220 //offsetWidth/offsetHeight(包含width_padding_border) console.log(this.offsetWidth) console.log(this.offsetHeight) } </script> </body>
client和offset区别: client不加border,offset加border
文档可视区宽高以及滚动距离计算(重要)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body style="height: 2000px;"> <script> //获取文档相关 //document是一个对象,对象没有宽高,必须要获取到html元素才有宽高 //document.documentElement 获取到的是整个html页面 //1 获取文档可视区的宽高 console.log(document.documentElement.clientWidth) console.log(document.documentElement.clientHeight) //2 获取页面宽高 console.log(document.documentElement.scrollWidth) console.log(document.documentElement.scrollHeight) // 3如何获取滚动距离 console.log(document.documentElement.scrollTop) console.log(document.documentElement.scrollLeft) //注意以上上问题时非常常用的,必须记住 </script> </body>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> #wrap{ width: 100%; height: 500px; background-color: rgb(0,0,0,0.5); position: fixed; left: 0; top: 0; display: none; } #box{ width: 300px; height: 300px; background-color: white; position: absolute; left: 0; top: 0; } h1 { background-color: #009F95; font-size: 16px; color: white; } </style> </head> <body style="height: 2000px;"> <!--需求:点击按钮 弹窗遮罩--> <button id="btn">click</button> <div id="wrap"> <div id="box"> <h1>登录</h1> </div> </div> <p style="margin-top: 1500px;">11111</p> <script> var oBtn = document.getElementById('btn') var oWrap = document.getElementById('wrap') var oBox = document.getElementById('box') oBtn.onclick = function(){ //让wrap显示 oWrap.style.display = 'block' var pageH = document.documentElement.scrollHeight oWrap.style.height = pageH + 'px' //让登录box居中显示,设置left和top var dleft = document.documentElement.clientWidth/2 - oBox.offsetWidth/2 var dtop = document.documentElement.clientHeight/2 - oBox.offsetHeight/2 //如果 dtop是负值,要重置为0 if(dtop <0 ){ dtop = 0 } oBox.style.left = dleft + 'px' oBox.style.top = dtop + 'px' window.onresize = function(){ //让登录box居中显示,设置left和top var dleft = document.documentElement.clientWidth/2 - oBox.offsetWidth/2 var dtop = document.documentElement.clientHeight/2 - oBox.offsetHeight/2 //如果 dtop是负值,要重置为0 if(dtop <0 ){ dtop = 0 } oBox.style.left = dleft + 'px' oBox.style.top = dtop + 'px' } } oWrap.onclick = function(){ this.style.display = 'none' } </script> </body> </html>
什么是BOM
BOM(Browse Object Model),浏览器对象模型,没有相关标准,是约定成俗的东西,定义了一些浏览器的方法和属性,大部分方法都是通过window对象来调用的,window对象是浏览器最顶层的对象。
DOM: 操作文档
BOM: 操作浏览器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body> <button id="btn1">打开</button> <button id="btn2">关闭</button> <script> var oBtn1 = document.getElementById('btn1') var oBtn2 = document.getElementById('btn2') var w = null oBtn1.onclick = function(){ //打开一个窗口,如果没有指定网址,则打开一个空白窗口 //第2个参数,是打开窗口的方式,不写默认是新开一个窗口,self是在本页面跳转 //返回的是新开窗口的对象 w = open('https://www.baidu.com') //open('https://www.baidu.com', '_self') } oBtn2.onclick = function(){ //关闭之前打开的窗口 w.close() } </script> </body>
BOM相关属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> console.log(window.navigator.userAgent) //Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 if(window.navigator.userAgent.indexOf("MSIE") != -1){ alert('当前浏览器是IE') }else{ alert('当前浏览器器不是IE') } </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//得到访问的地址 console.log(window.location.href) //得到地址栏问号后面的东西 ?wd='xx'&age=12 console.log(window.location.search) //得到地址栏#号后面的内容 console.log(window.location.hash)