DOM 的基本概念及操作
-
DOM(Document Object Model): 文档对象模型
-
其实就是操作 html 中的标签的一些能力
-
我们可以操作哪些内容
- 添加一个div
- 删除一个li
- 修改一个ol
- 获取某一个标签的样式
- 修改某一个而标签的样式
- 给某一个标签添加事件
- 给某一个标签添加属性
- 给元素添加一些 css 样式
- ...
-
DOM 的核心对象就是
document对象。 -
document 对象是浏览器内置的一个对象,内部提供了很多属性和方法,帮我们便捷的操作页面标签。
-
DOM: 页面中的标签, 我们通过 JS 获取到以后, 就把这个对象叫做 DOM 对象。
一、获取标签(元素)
- 通过 JS 代码来获取页面中的标签, 获取后我们就可以操作这些标签
1、获取非常规元素
- document.documentElement
- document.head
- document.body
// 1. html
var htmlEle = document.documentElement
console.log(htmlEle)
// 2. head
var headEle = document.head
console.log(headEle)
// 3. body
var bodyEle = document.body
console.log(bodyEle)
2、获取常规元素
- 通过 JS 代码来获取页面中的标签, 获取后我们就可以操作这些标签
1)getElementById
- getElementById 是通过标签的 ID 名称来获取标签的
- 因为页面中的 ID 是唯一的, 所以获取到的就是一个元素
<body>
<div id="box"></div>
<script>
var box = document.getElementById('box')
console.log(box) // 页面中 ID 为 box 的标签
</script>
</body>
2)getElementsByClassName
- getElementsByClassName 是通过标签的 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>
注意!!!getElementsByClassName 是一组长得很像数组的数据解构, 但它不是数组, 我们叫这种数据结构为:伪数组- 这一组数据也是按照索引排列的, 所以我们想要准确的拿到这个 div, 需要用索引来获取
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 元素
4)querySelector('像写CSS选择器一样书写标签')
- querySelector 是按照选择器的方式来获取元素
- 也就是说, 按照我们写 css 的时候的选择器来获取
- 这个方法只能获取到一个元素, 并且是页面中第一个满足条件的元素
- 返回值:符合条件的第一个标签
// 获取页面中第一个 div 元素
console.log(document.querySelector('div'))
// 获取页面中第一个 有 box 类名的元素
console.log(document.querySelector('.box'))
// 获取页面中第一个 id 名为 box2 的元素
console.log(document.querySelector('#box2'))
5)querySelectorAll
-
querySelectorAll 是按照选择器的方式来获取元素
-
这个方法能获取到所有满足条件的元素
-
返回值:返回一个符合条件的标签组成的
伪数组- 伪数组:长得很像数组,也有下标,也有length,但是数组的方法,很多都没有.控制台打印出来数组前面有nodelist
-
获取不存在的元素,返回值是
null
// 获取页面中的所有的 div 元素
console.log(document.querySelectAll('div'))
// 获取页面中的所有的 类名为 box 的元素
console.log(document.querySelectAll('.box'))
- 获取到的是一组数据, 也是需要用索引来获取到准确的每一个 DOM 元素
二、获取样式
1、style
- 专门用来个元素添加 css 样式的
1)行内样式
- 语法:
元素/标签.style - 能够拿到
行内样式,或者给添加一个新的行内样式;
<div style='width:100px;height:200px;background-color:blue;'></div>
var div = document.querySelector('div')
div.style.width = '100px'
div.style.hright = '100px'
div.style['background-color] = 'pink' //能获取,但是有点麻烦
div.style.backgroundColor = 'pink' //推荐写法(驼峰命名)
2)内部样式
- 语法:
getComputedStyle('要查询样式的标签').要查询的样式名 - 非行内样式和行内样式,都能正常获取,但是获取到的值不能修改,只读
<style>
.box {
width: 200px;
height: 200px;
background-color: lightblue;
}
</style>
<div class="box"></div>
<script>
var myDiv = document.querySelector('.box')
//因为元素的样式添加在了类名上,也就是非行内的,所以style获取不到
console.log(myDiv.style.width)//' '
//getComputedStyle('要查询样式的标签').要查询的样式名
console.log(getComputedStyle(myDiv).width)//200px
console.log(getComputedStyle(myDiv).height)//200px
//非行内样式和行内样式,都能正常获取,但是获取到的值不能修改
</script>
三、操作元素类名
1、className
- 语法:
元素/标签.className=> 能够得到元素目前拥有的类名 - 还可以给这个属性重新赋值,然后修改当前标签的类名
<div class="box1">你好 2310</div>
<script>
var box = document.querySelector('.box1')
console.log(box.className)//box1
//box.className = 'box2' 当前方式,不管之前有多少类名,全部重新覆盖掉
box.className += ' box2'//类名之间一定要加 空格
console.log(box.className)
//删除类名
box.className = ''//相当于清空之前的所有类名
</script>
- 在设置的时候, 不管之前有没有类名, 都会全部被设置的值覆盖
2、classList
- 语法:
元素/标签.classList - 返回值:是一个伪数组,数组内下标对应的是每一个类名,里边的
value属性对应的是我们完整类名的字符串
<div class="box1 abc why">你好 2310</div>
<script>
var box = document.querySelector('.box1')
console.log(box.classList)
//向div这个标签里面追加一个类名box2
//原本的类名不受影响
box.classList.add('box2')
//删除指定类名
// box.classList.remove('why')
console.log(box.classList)
</script>
3、自定义弹框案例
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
width: 100%;
height: 100%;
}
.overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
left: 0;
}
.msg_box {
width: 280px;
height: 170px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: aliceblue;
border-radius: 10px;
padding: 20px;
}
.msg_box p {
margin: 24px;
}
.close {
display: none;
}
.show {
display: block;
}
</style>
</head>
<body>
<!-- 点击打开弹出框 -->
<button id="show_msg_box">展示弹出框</button>
<!-- 灰色的遮罩层 -->
<div class="overlay close"></div>
<!-- 弹出层的信息展示 -->
<div class="msg_box close">
<h1>这是一个自定义弹出层</h1>
<p>广告位招租</p>
<!-- 点击关闭弹出层 -->
<button id="close_msg_box">关闭</button>
</div>
<script>
// 0. 获取标签
var showMsgBox = document.querySelector('#show_msg_box')
var closeMsgBox = document.querySelector('#close_msg_box')
var overlay = document.querySelector('.overlay') // 遮罩层
var msgBox = document.querySelector('.msg_box') // 信息框
// 添加事件
// 1. 打开弹窗框 遮罩层和弹出框的信息展示
showMsgBox.onclick = function () {
// 拿遮罩层举例, 删掉 close 添加类名 show
overlay.classList.remove('close')
overlay.classList.add('show')
// 信息框和上边的遮罩层相同
msgBox.classList.remove('close')
msgBox.classList.add('show')
}
// 2. 关闭弹出框 遮罩层和弹出框的信息隐藏
closeMsgBox.onclick = function () {
// 删掉 show, 添加 close
overlay.classList.remove('show')
overlay.classList.add('close')
msgBox.classList.remove('show')
msgBox.classList.add('close')
}
</script>
</body>
四、操作元素属性
- 我们获取到元素后, 可以直接操作 DOM的属性, 然后直接把效果展示在页面上
<div class="box" why1="一个自定义属性" data_name="张三">一个普通的div</div>
var box = document.querySelector('.box')
console.log(box)
1、获取标签属性
- 语法:
元素.getAttribute('属性名')
//1、获取标签属性
console.log(box.getAttribute('class'))//box
var res = box.getAttribute('why')
console.log(res)//一个自定义属性
2、设置标签属性
- 语法:
元素.setAttribute('属性名','属性值')
//2、设置标签属性
box.setAttribute('whynew2', '内容bee')
3、修改标签属性
- 语法:
元素.setAttribute('属性名','属性值')
//3、修改标签属性
box.setAttribute('class', 'whywhy3')
4、H5新增自定义属性
- H5自定义属性在书写的时候有一个固定的开头就是
data- - 完整语法:
data-属性名 = 属性值 - 获取的语法:
元素/标签.dataset.属性名(属性名不要带data-) - 注意点:在设置的时候,不要采用驼峰,全小写,因为就算大写了,浏览器也会转换为小写.
//4、H5新增自定义属性
//H5自定义属性在书写的时候有一个固定的开头就是data-
//完整语法:data-属性名 = 属性值
//获取的语法:元素/标签.dataset.属性名(属性名不要带data-)
//注意点:在设置的时候,不要采用驼峰,全小写,因为就算大写了,浏览器也会转换为小写
console.log(box.dataset.name)//张三
//新增
box.dataset.newname = '我是新增的属性'
5、getAttribute
- 获取元素的某个属性(包括自定义属性)
<div a="100" class="box"></div>
var div = document.querySelector('div')
console.log(div.getAttribute('a')) // 100
console.log(div.getAttribute('calss')) // box
6、setAttribute
- 给元素设置的一个属性(包括自定义属性)
<div></div>
var div = document.querySelector('div')
console.log(div.setAttribute('a', 100))
console.log(div.setAttribute('calss', box))
7、removeAttribute
- 直接移出元素的某个属性
<div a="100" class="box"></div>
var div = document.querySelector('div')
console.log(div.removeAttribute('calss'))
8、密码框案例
<input type="password">
<button>点击展示/隐藏密码</button>
<script>
// 0. 获取标签
var inp = document.querySelector('input')
var btn = document.querySelector('button')
// 添加事件
btn.onclick = function () {
// console.log(inp.getAttribute('type'))
// console.dir(inp.type)
// if (inp.type === 'password') {
// inp.type = 'text'
// } else {
// inp.type = 'password'
// }
inp.type = inp.type === 'password' ? 'text' : 'password'
}
// btn.onclick = function () {
// /**
// * 逻辑:
// * 如果当前是密码框, 那么更改为 输入框
// * 如果当前是输入框, 那么更改为 密码框
// */
// // inp.setAttribute('type', 'text')
// // console.log(inp.getAttribute('type'))
// if (inp.getAttribute('type') === 'password') {
// inp.setAttribute('type', 'text')
// } else {
// inp.setAttribute('type', 'password')
// }
// }
</script>
9、全选案例
全选: <input type="checkbox" class="all_btn">
<hr>
<input type="checkbox" class="item"> 兴趣1
<input type="checkbox" class="item"> 兴趣2
<input type="checkbox" class="item"> 兴趣3
<script>
// 0. 获取标签
var allBtn = document.querySelector('.all_btn')
var items = document.querySelectorAll('.item')
// 1. 给全选按钮添加点击事件
allBtn.onclick = function () {
for (var i = 0; i < items.length; i++) {
items[i].checked = allBtn.checked
}
}
// 2. 给所有的兴趣爱好添加事件
// 因为 items 是一个伪数组, 所以不能添加点击事件, 只有页面的元素/标签 才能添加
// items.onclick = function () {}
// items[0].onclick = function () { console.log(123) }
// items[1].onclick = function () { console.log(123) }
// items[2].onclick = function () { console.log(123) }
// 因为上述的代码比较复杂, 所以可以使用 一个循环进行优化 (前提是, 这几个函数的事件是一样的, 而我们目前案例中就是相同的事件功能)
// for (var i = 0; i < items.length; i++) {
// items[i].onclick = function () {
// console.log(123)
// }
// }
// console.log(setItemChecked) // 是一个函数体
// console.log(setItemChecked()) // undefined
// 拆分代码, 进行代码的优化(可读性)
for (var i = 0; i < items.length; i++) {
items[i].onclick = setItemChecked
// items[i].onclick = setItemChecked()
}
function setItemChecked() {
// console.log('判断内部的所有兴趣有没有被选中, 如果有那么选中 全选')
// 1. 要知道现在有没有全部选中 所有兴趣
var num = 0
for (var k = 0; k < items.length; k++) {
items[k].checked && num++
}
// console.log(num, items.length, num === items.length)
// 2. 根据上边的结果, 决定是否选中 全选
allBtn.checked = num === items.length
}
// allBtn.onclick = function () {
// // console.log(allBtn.checked)
// if (allBtn.checked === true) {
// // 选中 全选按钮, 勾选所有的兴趣按钮
// // items[0].checked = true
// // items[1].checked = true
// // items[2].checked = true
// // 上边的三行代码非常麻烦, 所以可以借助一个 for 循环优化
// for (var i = 0; i < items.length; i++) {
// items[i].checked = true
// }
// } else {
// // 取消勾选 全选按钮, 那么应该 取消勾选所有的兴趣按钮
// for (var i = 0; i < items.length; i++) {
// items[i].checked = false
// }
// }
// }
</script>
四、操作文本属性
1、innerHTML
- 获取元素内部的 HTML 解构
<div>
<p>
<span>hello</span>
</p>
</div>
var div = document.querySelector('div')
console.log(div.innerHTML) // <p><span>hello</span></p>
- 设置元素内部的 HTML 解构
<div></div>
var div = document.querySelector('div')
div.innerHTML = '<p><span>hello</span></p>'
2、innerText
- 获取元素内部的文本(只能获取到文本, 获取不到 html 标签)
<div>
<p>
<span>hello</span>
</p>
</div>
var div = document.querySelector('div')
console.log(div.innerHTML) // hello
- 设置元素内部的 HTML 解构
<div></div>
var div = document.querySelector('div')
div.innerHTML = '<p><span>hello</span></p>'
- 会把
<p><span>hello</span></p>当作一段文本出现在 div 元素内, 而不会把 p 解析成标签
3、value
- 专门给输入框添加展示文本
var msg = document.querySelector('#msg')
var inp = document.querySelector('#inp')
// msg.innerText = '你好'
// msg.innerHTML = '我不好'
// msg.value = '都不好' //value属性是给input输入框设置展示文本,所以设置无效
//如果想要给input输入框添加展示文本,需要借助value
inp.value = '你好 value'
4、区别
innerHTML/innerText能够给输入框之外的标签添加展示文本value专门给输入框添加展示文本innerHTML认识字符串中的标签,能够将字符串中的标签转换成真正的标签进行渲染;获取文本的时候,能够获取到元素的子集标签以及文本innerText不认识字符串中的标签;获取文本的时候,只能获取到元素的子级文本- 推荐使用
innerText能够防止用户注入恶意代码