DOM(Document Object Model): 文档对象模型
其实就是操作 html 中的标签的一些能力
可以操作哪些内容
- 获取一个元素
- 移除一个元素
- 创建一个元素
- 向页面里面添加一个元素
- 给元素绑定一些事件
- 获取元素的属性
- 给元素添加一些
css样式 - ...
DOM的核心对象就是docuemnt对象document对象是浏览器内置的一个对象,里面存储着专门用来操作元素的各种方法DOM: 页面中的标签,我们通过js获取到以后,就把这个对象叫做DOM 对象
获取元素
通过js来获取页面中的标签,获取到以后我们就可以操作这些标签了
1-1 getElementById
getElementById是通过标签的id名称来获取标签的- 如果一个元素有 id 特性(attribute),那我们就可以使用
document.getElementById(id) 方法获取该元素,无论它在哪里
-
因为在一个页面中
id是唯一的,所以获取到的就是一个元素<body> <div id="box"></div> <script> var box = document.getElementById('box') console.log(box) // <div></div> </script> </body>获取到的就是页面中的那个 id 为 box 的 div 标签
id 必须是唯一的
-
id 必须是唯一的。在文档中,只能有一个元素带有给定的 id 。
-
如果有多个元素都带有同一个 id ,那么使用它的方法的行为是不可预测的,例如document.getElementById 可能会随机返回其中一个元素。因此,请遵守规则,保持 id 的唯一性。
1-2 getElementsByClassName
-
getElementsByClassName是用过标签的class名称来获取标签的 -
因为页面中可能有多个元素的
class名称一样,所以获取到的是一组元素 -
哪怕你获取的
class只有一个,那也是获取一组元素,只不过这一组中只有一个 DOM 元素而已<body> <div calss="box"></div> <script> var box = document.getElementsByClassName('box') console.log(box) // [<div></div>] console.log(box[0]) // <div></div> </script> </body>- 获取到的是一组元素,是一个长得和数组一样的数据结构,但是不是数组,是 伪数组
- 这个一组数据也是按照索引排列的,所以我们想要准确的拿到这个
div,需要用索引来获取
1-3 getElementsByTagName
-
getElementsByTagName是用过标签的 标签 名称来获取标签的 -
因为页面中可能有多个元素的 标签 名称一样,所以获取到的是一组元素
-
哪怕真的只有一个这个标签名,那么也是获取一组元素,只不过这一组中只有一个 DOM 元素而已
<body> <div></div> <script> var box = document.getElementsByTagName('div') console.log(box) // [<div></div>] console.log(box[0]) // <div></div> </script> </body>- 和
getElementsByClassName一样,获取到的是一个长得很像数组的元素 - 必须要用索引才能得到准确的
DOM元素
- 和
1-4 querySelector
-
querySelector是按照选择器的方式来获取元素 -
也就是说,按照我们写
css的时候的选择器来获取 -
这个方法只能获取到一个元素,并且是页面中第一个满足条件的元素
-
结果与 elem.querySelectorAll(css)[0] 相同,但是后者会查找 所有元素,并从中选一个,
elem.querySelector只会查找一个。因此它在速 度上更快,并且写起来更短。console.log(document.querySelector('div')) // 获取页面中的第一个 div 元素 console.log(docuemnt.querySelector('.box')) // 获取页面中第一个有 box 类名的元素 console.log(document.querySelector('#box')) // 获取页面中第一个 id 名为 box 的元素
1-5 querySelectorAll
此方法是最为通用的 elem.querySelectorAll(css)
-
querySelectorAll是按照选择器的方式来获取元素 -
这个方法能获取到所有满足条件的元素,以一个伪数组的形式返回
-
只会返回一个对象,第一个
console.log(document.querySelectorAll('div')) // 获取页面中的所有的 div 元素 console.log(docuemnt.querySelectorAll('.box')) // 获取页面中所有有 box 类名的元素- 获取到的是一组数据,也是需要用索引来获取到准确的每一个
DOM元素
- 获取到的是一组数据,也是需要用索引来获取到准确的每一个
matches
elem.matches(css)不会查找任何内容,他只会检查elmem 是否与给定的CSS选择器匹配。他返回true 或者false
当我们遍历元素并试图过滤那些我们感兴趣的元素时,这个方法很有用。
closest
- 元素的祖先是:父级,父级的父级,他的父级。
- elem.closest(css)方法会查找与CSS选择器匹配的最近的祖先 elem自己也会被搜索
- closest(css)检查每个父级。若他与选择器匹配,则停止搜索并返回该祖先。
总结:
有6种主要的方法,可以在DOM中搜索节点
操作元素属性
2-1 innerHTML
-
获取元素内部的
HTML结构<body> <div> <p> <span>hello</span> </p> </div> <script> var div = document.querySelector('div') console.log(div.innerHTML) /* <p> <span>hello</span> </p> */ </script> </body> -
设置元素的内容
<body> <div></div> <script> var div = document.querySelector('div') div.innerHTML = '<p>hello</p>' </script> </body>- 设置完以后,页面中的
div元素里面就会嵌套一个p元素
- 设置完以后,页面中的
2-2 innerText
-
获取元素内部的文本(只能获取到文本内容,获取不到
html标签)<body> <div> <p> <span>hello</span> </p> </div> <script> var div = document.querySelector('div') console.log(div.innerText) // hello </script> </body> -
可以设置元素内部的文本
<body> <div></div> <script> var div = document.querySelector('div') div.innerText = '<p>hello</p>' </script> </body>- 设置完毕以后,会把
<p>hello</p>当作一个文本出现在div元素里面,而不会把p解析成标签
- 设置完毕以后,会把
2-3 getAttribute
-
获取元素的某个属性(包括自定义属性)
<body> <div a="100" class="box"></div> <script> var div = document.querySelector('div') console.log(div.getAttribute('a')) // 100 console.log(div.getAttribute('class')) // box </script> </body>
2-4 setAttribute
-
给元素设置一个属性(包括自定义属性)
<body> <div></div> <script> var div = document.querySelector('div') div.setAttribute('a', 100) div.setAttribute('class', 'box') console.log(div) // <div a="100" class="box"></div> </script> </body>
2-5 removeAttribute
-
直接移除元素的某个属性
<body> <div a="100" class="box"></div> <script> var div = document.querySelector('div') div.removeAttribute('class') console.log(div) // <div a="100"></div> </script> </body>
2-6 style
-
专门用来给元素添加
css样式的 -
添加的都是行内样式
-
直接赋值即可
<body> <div></div> <script> var div = document.querySelector('div') div.style.width = "100px" div.style.height = "100px" div.style.backgroundColor = "pink" console.log(div) // <div style="width: 100px; height: 100px; background-color: pink;"></div> </script> </body>- 页面中的
div就会变成一个宽高都是100,背景颜色是粉色
- 页面中的
2-7 获取元素的非行间样式
-
我们在操作
DOM的时候,很重要的一点就是要操作元素的css样式 -
那么在操作
css样式的时候,我们避免不了就要获取元素的样式 -
可以用
元素.style.xxx来获取但是这个只能获取到元素 行间样式,也就是写在行内的样式<style> div { width: 100px; } </style> <body> <div style="height: 100px;"> <p>我是一个 p 标签</p> </div> <script> var oDiv = document.querySelector('div') console.log(oDiv.style.height) // 100px console.log(oDIv.style.width) // '' </script> </body>
无论是外链式还是内联式都获取不到该元素的样式,使用getComputedStyle(非IE)和 currentStyle来获取。
区别一个在非IE浏览器中,一个在IE浏览器中
getComputedStyle(非IE使用)
只能获取样式,不能赋值写样式
-
语法:
window.getComputedStyle(元素, null).要获取的属性<style> div { width: 100px; } </style> <body> <div style="height: 100px;"> <p>我是一个 p 标签</p> </div> <script> var oDiv = document.querySelector('div') console.log(window.getComputedStyle(oDiv).width) // 100px console.log(window.getComputedStyle(oDiv).height) // 100px </script> </body>- 这个方法获取行间样式和非行间样式都可以
currentStyle(IE使用)
-
语法:
元素.currentStyle.要获取的属性<style> div { width: 100px; } </style> <body> <div style="height: 100px;"> <p>我是一个 p 标签</p> </div> <script> var oDiv = document.querySelector('div') console.log(oDiv.currentStyle.width) // 100px console.log(oDiv.currentStyle.height) // 100px </script> </body>
2-8 className
-
专门用来操作元素的 类名的
<body> <div class="box"></div> <script> var div = document.querySelector('div') console.log(div.className) // box </script> </body> -
要删除上一个直接赋一个新的命名
-
也可以设置元素的类名,不过是全覆盖式的操作
<body> <div class="box"></div> <script> var div = document.querySelector('div') div.className = 'test' console.log(div) // <div class="test"></div> </script> </body>在设置的时候,不管之前有没有类名,都会全部被设置的值覆盖
2-9 classlist属性
可以进行一个一个的删除
console.log(box.classList)
box.classList.remove("item2)
box.classList.remove("item1)
总结:
要管理class,有两个DOM属性
className字符串值,可以很好管理整个类的集合classList——具有add/remove/toggle/contains 方法的对象,可以很好的支持单类的。
要改变样式:
style属性是具有驼峰(camelCased)样式的对象。对其进行读取和修改与修改
- "style" 特性(attribute)中的各个属性具有相同的效果。要了解如何应用
-
important和其他特殊内容 — 在MDN中有一个方法列表。 -
style.cssText属性对应于整个"style"特性(attribute),即完整的样式字符串。
要读取解析的(resolved)样式(对于所有类,在应用所有 CSS 并计算最终值之后。
- getComputedStyle(elem, [pseudo]) 返回与 style 对象类似的,且包含了所有类的对象。只读。
toggle切换
原本有则为删除,原本没有则为增加
<body>
<button id="btn">click</button>
<script>
btn.onclick = function(){
box.classList.toggle("item)
}
</script>
DOM节点
常用的三大类:元素节点/文本节点/属性节点
- 元素节点
- document不是元素节点,叫做根节点
- html最大的元素节点,根元素节点
- head/body/div/ul/... 都为元素节点
- 文本节点
是一段文本,包含换行和空格
- 属性节点 如:div / input
- 注释节点
- 是一段注释也是节点,单独书写的不会显示在页面
获取节点
<body>
<div>
kerwin
2. <p>11111111</p>
3.<!--我是注释-->
</div>
- \n kerwin \n
- 文本节点
- \n
- 注释节点
- \n
childNodes属性 VS children
- childNodes:获取所有节点
- child:获取所有元素节点
firstchild VS firstElementchild
firstchild:获取某一节点下子一级的第一个节点
firstElementChild:获取某一节点下子一级第一个元素节点
<body>
<div>
<p>hello</p>
</div>
<script>
// 这个 oDiv 获取的是页面中的 div 元素,就是一个元素节点
var oDiv = document.querySelector('div')
console.log(oDiv.firstElementChild) // <p>hello</p>
</script>
</body>
lastchild VS lastElementchild
lastChild:获取某一节点下子一级的 最后一个节点
previousSibling VS previousElementSibling
获取某节点上一个兄弟节点
nextSibling VS nextElementSibling
获取某节点下一个兄弟节点
nextElementSibling:获取某一个节点的下一个元素节点
<body>
<ul>
<li id="a">hello</li>
<li id="b">world</li>
<li id="c">!!!</li>
</ul>
<script>
// 这个 oLi 获取的是页面中的 li 元素,就是一个元素节点
var oLi = document.querySelector('#b')
console.log(oLi.nextSibling) // #text
</script>
</body>
parentNode VS parentElementNode
获取父节点,二者基本差不多
删除节点(节点对象)
替换节点
<script>
var odiv2= document.createElement("div")
odiv2.innerHTML = "22222"
box.replaceChild(odiv2,child)
克隆节点
- true 克隆后代
- false不克隆后代
attributes:获取某一个 元素节点 的所有 属性节点
节点属性
- 元素节点没有 nodeValue
- 属性节点的 nodeValue 就是属性值
- 文本节点的 nodeValue 就是文本内容
- 元素节点的
nodeName就是 大写标签名 - 属性节点的
nodeName就是 属性名 - 文本节点的
nodeName都是 #text
获取元素属性
<style>
div{
wiidth:100px;
height:100px;
padding1:10px;
border:5px solid red;
background-color:yellow;
}
</style>
console.log(getComputedStyle(box).width)
//获得的为内容的宽度100px
console。log(box.style.width)
//获得的为行内宽度
console.log(box.offsetwidth,box.offsetHeight)
//offset (border+padding+content)
- 单位:数字类型
box-sizing计算方式无影响display:none拿不到
client=(padding+content)
获取元素偏移量
offsetParent
- 获取元素的偏移量参考父级
- 其实就是假设你要给一个元素 绝对定位 的时候
- 根据谁来进行定位的,这个元素的偏移量参考父级就是谁
- 被用来计算坐标
最近的祖先为下列之一:
- CSS定位的(
position为absolute,relative或fixed) - 或
<td>,<th>,<table> - 或
<body>
offsetLeft 和 offsetTop
- 获取的是元左边的偏移量和上边的偏移量
offsetLeft: 该元素相对于参考父级的左侧偏移量offsetTop: 该元素相对于参考父级的上侧偏移量
以下几种情况下,offsetParent的值为null:
- 对于未显示的元素(display:none 或者不在文档中)
- 对于
<body>与<html> - 对于带有position:fixed的元素 参考点 :定位父级
- 子盒子第一个遇到有定位的父节点
- 父级元素没有定位则参考body
clientLeft 和 clientTop
计算距离自己左上角的位置
准确来说,这些属性不是边框的width/height,而是内侧与外侧的相对坐标
ul{
width:200px;
height:200px;
padding:20px;
border:10px solidblack;
background:red;
margin:50px;
border-Left-width:50px;
border-top-width:50px;
}
<body>
<script>
console.log(list.clientLeft,list.clientTop)
结果:50 50
总结:
元素具有以下几何属性:
-
offsetParent— 是最接近的 CSS 定位的祖先,或者是 td , th , table ,body -
offsetLeft/offsetTop— 是相对于offsetParent -
offsetWidth/offsetHeight— 元素的“外部” width/height,边框(border)尺的左上角边缘的坐标 -
clientLeft/clientTop— 从元素左上角外角到左上角内角的距离。对于从左到右显示内容的操作系统来说,它们始终是左侧/顶部 border 的宽度。而对于从右到左显示内容的操作系统来说,垂直滚动条在左边,所clientLeft也包括滚动条的宽度 -
clientWidth/clientHeight— 内容的width/height,包括padding,但不包括滚动条(scrollbar) -
scrollWidth/scrollHeight-内容的width/height 就像clientWidth/clientHeight-一样,但还包括元素滚动出不可见的部分。 -
scrollLeft/scrollTop-从元素的左上角开始,滚动出元素的上半部分的width/height -
除了
scrollLeft/scrollTop外,所有属性都是只读的 -
若修改
scrollLeft/scrollTop浏览器会滚动对应的元素
获取可视窗口的尺寸
-
窗口包含滚动条的尺寸
innerWidthinnerHeight -
获取不包含滚动条的尺寸
document.documentElement.clientWidth: 可视窗口的宽度document.documentElement.clientHeight: 可视窗口的高度
懒加载:到底之后再进行加载数据
创建滑动菜单
HTML样式:
<div class="menu">
<span class="title">Sweeties (click me)!</span>
<ul>
<li>Cake</li>
<li>Donut</li>
<li>Honey</li>
</ul>
</div>
CSS样式
<div style="border: solid red 1px" onclick="alert(1)">Sweeties (click me)!</di
切换菜单应更改箭头并显示/隐藏菜单列表
在Javascript中应通过添加/移除.open类来标记菜单的当前状态,没有他菜单就会被关闭:
.menu ul {
margin: 0;
list-style: none;
padding-left: 20px;
display: none;
}
.menu .title::before {
content: '▶ ';
font-size: 80%;
color: green;
}
……有.open后,箭头就会改变,列表就会出现
.menu.open .title::before {
content: '▼ ';
}
.menu.open ul {
display: block;
}