一三四、JavaScript——_DOM简介
MDNq前端参考文档:DOM 概述 - Web API 接口参考 | MDN (mozilla.org)
一三五、JavaScript——HelloWorld
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">点我一下</button>
<script>
/*
要使用DOM来操作网页,我们需要浏览器至少先给我一个对象
才能去完成各种操作
所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用
document代表的是整个网页
*/
// 打印document 和在控制台中访问document.window效果是一样的
console.log(document)
// 获取btn对象,获取id为"btn"的元素
const btn = document.getElementById("btn")
//console.log(btn)
// 修改btn中的文字,通过innerText修改即可
btn.innerText = "Click ME"
</script>
</body>
</html>
// 打印document 和在控制台中访问document.window效果是一样的
console.log(document)
// 获取btn对象,获取id为"btn"的元素
const btn = document.getElementById("btn")
//console.log(btn)
// 修改btn中的文字,通过innerText修改即可
btn.innerText = "Click ME"
一三六、JavaScript——文件节点
document的整个原型链:
MDN前端参考文档关于Document的部分:https://developer.mozilla.org/zh-CN/docs/Web/API/Document
document对象
- document对象表示的是整个网页
- document对象的原型链
本身 -> 父类 -> 父类的父类 -> 父类的父类的父类 -> 父类的父类的父类 ->父类的父类的父类的父类
HTMLDocument -> Document -> Node -> EnventTarget -> Object.prototype ->null
- 凡是在原型链上存在的对象的属性和方法都可以通过Document去调用
- 部分属性:
document.documentElement -- > html根元素
document.head -- > head元素
document.title -- > title元素
document.link -- > 获取页面中所有的超链接
...
一三七、JavaScript——获取元素节点
// 获取body标签以及body标签内的内容
console.log(document.body)
<button id="btn">点我一下</button>
<script>
// 通过id获取按钮
const btn = document.getElementById("btn")
console.log(btn)
</script>
元素节点对象(element)
- 在网页中,每一个标签都是一个元素节点
- 如何获取元素节点对象
1. 通过document对象来获取元素节点
2. 通过document创建元素节点
- 通过document获取已有的元素节点对象
document.getElementById()
- 根据id获取一个元素节点对象(只能获取一个,因为id是不能重复的)
document.getElementsByClassName()
- 根据元素的class属性获取一组元素节点对象
document.getElementsByClassName()
- 根据元素的class属性值获取一组元素节点对象
- 返回的是一个类数组对象
- 该方法返回的结果是一个实时更新的集合
当网页中新添加元素时,集合也会实时的刷新
document.getElementsByTagName()
- 根据标签名获取元素节点对象
- 返回的结果是实时更新的集合
- document.getElementsByTagName("*"): 获取页面中的所有元素
document.querySelectorAll()
- 根据选择器去页面中查询元素
- 会返回一个数组(不会实时更新)
document.querySelector()
- 根据选择器去页面中查询第一个符合条件的元素
<body>
<button id="btn">点我一下</button>
<span class="s1">我是pan</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>
<form>
<input type="text" name="username">
<input type="radio" name="gender" value="男">
<input type="radio" name="gender" value="女">
</form>
<script>
/*
元素节点对象(element)
- 在网页中,每一个标签都是一个元素节点
- 如何获取元素节点对象
1. 通过document对象来获取元素节点
2. 通过document创建元素节点
- 通过document获取已有的元素节点对象
document.getElementById()
- 根据id获取一个元素节点对象(只能获取一个,因为id是不能重复的)
document.getElementsByClassName()
- 根据元素的class属性获取一组元素节点对象
document.getElementsByClassName()
- 根据元素的class属性值获取一组元素节点对象
- 返回的是一个类数组对象
- 该方法返回的结果是一个实时更新的集合
当网页中新添加元素时,集合也会实时的刷新
document.getElementsByTagName()
- 根据标签名获取元素节点对象
- 返回的结果是实时更新的集合
- document.getElementsByTagName("*"): 获取页面中的所有元素
document.querySelectorAll()
- 根据选择器去页面中查询元素
- 会返回一个数组(不会实时更新)
document.querySelector()
- 根据选择器去页面中查询第一个符合条件的元素
*/
// 获取body标签以及body标签内的内容
console.log(document.body)
// 通过id获取按钮
const btn = document.getElementById("btn")
console.log(btn)
// 通过Class的id的name获取span的内容
const spans = document.getElementsByClassName("s1")
// 遍历span标签的内容
for(let i=0; i<spans.length; i++){
//将内容都改为“哈哈哈”
spans[i].innerText = "哈哈哈"+ i
}
console.log(spans)
// 根据标签名div获取元素节点对象
const divs = document.getElementsByTagName("div")
// 获取页面中的所有元素
const tagName = document.getElementsByTagName("*")
console.log(tagName)
// 针对form表单中的input
const genderInput = document.getElementsByName("gender")
console.log(genderInput)
// 获取所有标签元素为div的
const divs2 = document.querySelectorAll("div")
// 打印的是一个集合 NodeList(5) [div, div, div, div, div]
console.log(divs2)
// 获取标签元素为div的,取单个的,一般情况就取第一个
const divs3 = document.querySelector("div")
// 在控制台直接打印div,点击显示的是第一个div标签
</script>
</body>
一三八、JavaScript——元素的属性和方法
通过元素节点对象获取其他的节点的方法
element.childNodes 获取当前元素的子节点(会包含空白的节点)
子节点包括:文本节点、标签节点等,
标签节点后还有空白节点,所以算两个节点,而文本节点后的空白节点是被文本节点一起包含的
element.children 获取当前元素的子元素
element.firstElementChild 获取当前元素第一个子元素
element.lastElementChild 获取当前元素第一个子元素
element.nextElementSibling 获取当前元素的下一个兄弟元素
element.previousElementSibling 获取当前元素的前一个兄弟元素
element.parentNode 获取当前元素的父节点
element.tagName 获取当前元素的标签名
<body>
<div id="box1">
我是box1
<span class="s1">我是s1</span>
<span class="s1">我是s1</span>
</div>
<span class="s1">我是s1</span>
<script>
/*
div元素的原型链
HTMLDivElement -> HTMLElement -> Elemnet -> Node -> ---
通过元素节点对象获取其他的节点的方法
element.childNodes 获取当前元素的子节点(会包含空白的节点)
子节点包括:文本节点、标签节点等,
标签节点后还有空白节点,所以算两个节点,而文本节点后的空白节点是被文本节点一起包含的
element.children 获取当前元素的子元素
element.firstElementChild 获取当前元素第一个子元素
element.lastElementChild 获取当前元素第一个子元素
element.nextElementSibling 获取当前元素的下一个兄弟元素
element.previousElementSibling 获取当前元素的前一个兄弟元素
element.parentNode 获取当前元素的父节点
element.tagName 获取当前元素的标签名
*/
// 获取id为box1的标签。通过documnet去调,则是通过整个网页范围内查找
const box1 = document.getElementById("box1")
//
console.log(box1)
// 通过box1去调,调用的范围只在box1的标签名内查找
const spans = box1.getElementsByTagName("span")
// 打印结果为2,name为box1的标签内的span标签数量为2
console.log(spans)
// 标签节点后还有空白节点,所以算两个节点,而文本节点后的空白节点是被文本节点一起包含的。算一个
const cns = box1.childNodes
// 结果为5,说明节点数为5
// 文本节点一个 标签节点两个 标签节点后的空白节点两个 共5个
console.log(cns)
</script>
</body>
一三九、JavaScript——文本节点
<body>
<img src="" alt="">
<!-- "我是div"在这里就是一个文本节点 -->
<div id="box1">
<span>我是box1</span>
</div>
<script>
/*
在DOM中,网页中的所有文本内容都是文本对象
可以通过元素来获取其中的文本节点对象,但是我们通常不会这么做
我们可以直接通过元素去修改其中的文本
修改文本的三个属性
element.textContent 获取或修改元素中的文本内容
- 获取的是标签中的内容,不会考虑css样式
- 不考虑样式就是本来的文本是大写,但通过textContent拿到的就是小写
element.innerText 获取或修改元素中的文本内容
- innerText获取内容时,会考虑css样式
- 考虑样式就是本来的文本是大写,但通过innerText拿到的就是大写,保留原有样式
- 当字符串中有标签时,会自动对标签进行转义,并不是真正的字符
element.innerHTML 获取或修改HTML中的代码
- 可以直接向元素中添加HTML代码
- innerHTML插入内容时,有被xss注入的风险
*/
// 先通过id获取到标签的内容
const box1 = document.getElementById("box1")
// 通过element.textContent修改文本内容
// box1.textContent = "新的内容"
</script>
</body>
一四零、JavaScript——属性节点
属性节点(Attr)
- 在DOM中也是一个对象,通常不需要获取对象而是直接通过元素即可完成对其的各种操作
- 如何操作属性节点:
方式一:
读取:元素.属性名(注意:class属性需要用className来读取)
读取一个布尔值时,会返回true或false
修改: 元素.属性名 = 属性值
方式二:
读取:元素.getAttribute(属性名)
修改:元素.setAttribute(属性名,属性值)
删除:元素.removeAttribute(属性名)
<body>
<input type="text" name="username" value="admin">
<script>
/*
属性节点(Attr)
- 在DOM中也是一个对象,通常不需要获取对象而是直接通过元素即可完成对其的各种操作
- 如何操作属性节点:
方式一:
读取:元素.属性名(注意:class属性需要用className来读取)
读取一个布尔值时,会返回true或false
修改: 元素.属性名 = 属性值
方式二:
读取:元素.getAttribute(属性名)
修改:元素.setAttribute(属性名,属性值)
删除:元素.removeAttribute(属性名)
*/
// getElementsByName 因为获取的是Elements,要想获取一个需要加一个索引[0]
const input = document.getElementsByName("username")[0]
// 打印内容为:<input type="text" name="username" value="admin">
console.log(input)
const input1 = document.querySelector("[name=username]")
console.log(input)
// 修改:元素.setAttribute(属性名,属性值)
input.setAttribute("value","孙悟空")
</script>
</body>
一四一、JavaScript——事件
事件(event)
- 事件就是用户和页面之间发生的交互行为
比如:点击按钮、鼠标移动、双击按钮、敲击键盘、松开键盘...
- 可以通过为事件绑定响应函数(回调函数),来完成用户之间的交互
- 绑定响应函数的方式
1. 可以直接在元素的属性中设置
2. 可以通过为元素的指定属性设置回调函数的形式来绑定事件
3. 可以通过元素addEventListener()方法来绑定事件
<body>
<!-- ondblclick指双击按钮跳出弹框 -->
<!-- <button id="btn" ondblclick="alert('你点我干嘛')">点我一下</button> -->
<button id="btn">点我一下</button>
<script>
/*
事件(event)
- 事件就是用户和页面之间发生的交互行为
比如:点击按钮、鼠标移动、双击按钮、敲击键盘、松开键盘...
- 可以通过为事件绑定响应函数(回调函数),来完成用户之间的交互
- 绑定响应函数的方式
1. 可以直接在元素的属性中设置
2. 可以通过为元素的指定属性设置回调函数的形式来绑定事件
3. 可以通过元素addEventListener()方法来绑定事件
*/
// 1.获取到按钮对象
const btn = document.getElementById("btn")
// 2.为按钮对象的事件属性设置响应函数,即点击了就会响应
btn.onclick = function(){
alert("点击按钮后调用的函数")
}
// 设置了新的绑定之后,新的绑定会将旧的绑定覆盖
btn.onclick = function(){
alert("设置新的绑定")
}
// 3. 通过元素addEventListener()方法来绑定事件
btn.assEventListener("click", function(){
alert("哈哈哈")
})
// 不会被覆盖,按顺序依次出现
btn.assEventListener("click", function(){
alert("嘻嘻嘻")
})
</script>
</body>
一四二、JavaScript——文档的加载
- 网页是自上而下加载的,如果将js代码编写到网页的上边(button按钮的上面
- js代码在执行时候,网页还没有加载完毕,这时候会出现无法获取到DOM对象的情况
window.onload 事件会在窗口中的内容加载完毕之后才触发
- 会等待所有文档都加载完成才会触发
document对象的DOMContentLoaded事件会在窗口中的内容加载完成之后才会触发
- 当前文档加载完成就触发
如何解决这个问题:
1. 将script标签写到body标签的最后的位置
2. 将代码编写到window.onload的回调函数中,因为window.onload的回调函数是最后执行的,所以此时script可以放在任意位置,只要放在里面就可以最后执行
3. 将代码编写到document对象的DOMContentLoaded的回调函数中(执行的时机早)
4. 将代码编写到外部的js文件中,然后以defer的形式引入(执行的时机更早,早于DOMContentLoaded)
开发过程中常用1,引外部文件时常用4
<body>
<button id="btn">点我一下</button>
<script>
/*
网页是自上而下加载的,如果将js代码编写到网页的上边(button按钮的上面)
js代码在执行时候,网页还没有加载完毕,这时候会出现无法获取到DOM对象的情况
window.onload 事件会在窗口中的内容加载完毕之后才触发
- 会等待所有文档都加载完成才会触发
document对象的DOMContentLoaded事件会在窗口中的内容加载完成之后才会触发
- 当前文档加载完成就触发
如何解决这个问题:
1. 将script标签写到body标签的最后的位置
2. 将代码编写到window.onload的回调函数中,因为window.onload的回调函数是最后执行的,所以此时script可以放在任意位置,只要放在里面就可以最后执行
3. 将代码编写到document对象的DOMContentLoaded的回调函数中(执行的时机早)
4. 将代码编写到外部的js文件中,然后以defer的形式引入(执行的时机更早,早于DOMContentLoaded)
开发过程中常用1,引外部文件时常用4
*/
// 可以放在任意位置,因为window.onload的回调函数总在最后执行
// window.onload() = function(){
// const btn = document.getElementById("btn")
// console.log(btn)
// }
// document对象的DOMContentLoaded的回调函数,只能通过 document.addEventListener调用
document.addEventListener("load", function (){
const btn = document.getElementById("btn")
console.log(btn)
})
const btn = document.getElementById("btn")
console.log(btn)
</script>
<!-- 代码编写到外部的js文件中,然后以defer的形式引入 -->
<!-- <script defer src="链接"></script> -->
一四六、JavaScript——元素的修改
appendChild() 用于给节点添加一个子节点
insertAdjacentElement(添加的位置,要添加的元素) 可以向元素任意位置添加元素i
添加的位置:
beforeend:标签的最后
afterbegin:标签的开始
beforebeing:与标签处于同级,在标签的前边插入元素(兄弟元素)
afterend:与标签处于同级,在标签的后边插入元素(兄弟元素)
insertAdjacentHTML("插入的位置", "插入的标签")
replaceWith("参与替换掉的元素")
remove() 方法来删除元素
<body>
<button id="btn01">按钮01</button>
<button id="btn02">按钮02</button>
<hr>
<ul id="list">
<li id="swk">孙悟空</li>
<li id="zbj">猪八戒</li>
<li id="shs">沙和尚</li>
</ul>
<script>
/*
点击按钮后,向ul中添加一个唐僧
*/
// 获取ul
const list = document.getElementById("list")
// 获取按钮
const btn01 = document.getElementById("btn01")
const btn02 = document.getElementById("btn02")
btn01.onclick = function() {
// 创建一个li
const li = document.createElement("li")
// 向li中添加文本
li.textContent = "唐僧"
// 给li添加id属性
li.id = "ts"
// // appendChild() 用于给节点添加一个子节点
// list.appendChild(li)
// console.log(list)
// insertAdjacentElement(添加的位置,要添加的元素)可以向元素任意位置添加元素i
// 两个参数:1.添加的位置 2.要添加的元素
/*
添加的位置:
beforeend:标签的最后
afterbegin:标签的开始
beforebeing:与标签处于同级,在标签的前边插入元素(兄弟元素)
afterend:与标签处于同级,在标签的后边插入元素(兄弟元素)
*/
list.insertAdjacentElement("afterbegin",li)
// insertAdjacentHTML("插入的位置", "插入的标签")
list.insertAdjacentHTML("", "<li id='bgj'>白骨精</li>")
}
btn02.onclick = function() {
// 创建一个蜘蛛精替换孙悟空
const li = document.createElement("li")
li.textContent = "蜘蛛精"
li.id = "zzj"
// 获取孙悟空
const swk = document.getElementById("swk")
// replaceWith() 使用一个元素替换当前元素
// replaceWith("参与替换掉的元素")
swk.replaceWith(li)
// remove() 方法来删除元素
swk.remove()
}
</script>
</body>
一五零、JavaScript——节点的复制
涉及的方法
添加:list.appendChild(l1)
将l1添加到list中
复制:const newL1 = li.cloneNode(true)
复制l1和l1下的子节点,l1标签里的文本节点就属于l1的子节点
<body>
<button id="btn01">点我一下</button>
<ul id="list1">
<li id="l1">孙悟空</li>
<li id="l2">猪八戒</li>
<li id="l3">孙悟空</li>
</ul>
<ul id="list2">
<li >蜘蛛精</li>
</ul>
<script>
/*
涉及的方法
添加:list.appendChild(l1)
将l1添加到list中
复制:const newL1 = li.cloneNode(true)
复制l1和l1下的子节点,l1标签里的文本节点就属于l1的子节点
*/
/*
点击按钮后,将id为l1的元素添加到list2中
*/
// 先获取按钮
const btn01 = document.getElementById("btn01")
const list2 = document.getElementById("list2")
const l1 = document.getElementById("l1")
// 点击按钮触发的函数
btn01.onclick = function() {
/*
使用 cloneNode()方法对节点进行复制时,它会复制节点的所有特点包括各种属性
这个方法只会默认复制当前节点,即只复制标签节点,不会复制文本节点,
可以传递一个true作为参数,这样该方法也会将元素的子节点一起复制
*/
const newL1 = li.cloneNode(true) // 用来对节点进行复制
// 防止id完全重复,重新赋值一个id即可
newL1.id = "newL1"
// 利用appendChild,点击按钮后,将l1添加到list2中去
list2.appendChild(l1)
}
</script>
</body>
一五一、JavaScript——修改css样式
在stylE标签中,
在样式的结尾在结尾加 !important
表示优先级最高,最先执行
background-color: #4ead56 !important;
修改样式的方式: 元素.style.样式名 = 样式值
如果样式名中含有"-",例如"background-color"则需要将样式表修改为驼峰命名法"backgroundColor"
"background-color" -> "backgroundColor"
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #4ead56 !important;
/*
在stylE标签中,
在样式的结尾在结尾加 !important
表示优先级最高,最先执行
background-color: #4ead56 !important;
*/
}
</style>
</head>
<body>
<button id="btn">点我一下</button>
<hr />
<div class="box1"></div>
<script>
/*
点击按钮后,修改box1的宽度
*/
const btn = document.getElementById("btn")
// querySelector方法:选中页面中出现的第一个标签
const box1 = document.querySelector(".box1")
// 点击按钮触发的函数
btn.onclick = function() {
// 修改.box1的样式
// 修改样式的方式: 元素.style.样式名 = 样式值
box1.style.width = "600px"
box1.style.height = "600px"
// 如果样式名中含有"-",例如"background-color"则需要将样式表修改为驼峰命名法"backgroundColor"
// "background-color" -> "backgroundColor"
box1.style.backgroundColor = "yellow";
}
</script>
</body>
一五二、JavaScript——读取样式
getComputedStyle()
-它会返回一个对象,这个对象中包含了当前元素的所有生效的样式
- 获取具体的样式数值:对象.width 获取样式的宽度
- 伪元素获取样式信息:getComputedStyle(要获取的样式对象, "要获取的为元素")
宽度以及高度的计算:
- 一般通过: "对象.width" 读取样式宽度时,都是带宽度的
- 通过 parseInt(对象.width)将 200px 中的px消除
- 再通过 + "px" 的方式加上单位
返回值
- 返回的一个对象,对象中存储了当前元素的样式
注意
- 样式对象中返回的样式值,不一定能拿来直接计算,有可能是auto
所以使用时,一定要确保值偶是可以计算的才去计算
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #4ead56 !important;
/*
在stylE标签中,
在样式的结尾在结尾加 !important
表示优先级最高,最先执行
background-color: #4ead56 !important;
*/
}
/*
伪元素
*/
.box1::before {
content: "hello";
color:red;
}
</style>
</head>
<body>
<button id="btn">点我一下</button>
<hr />
<div class="box1"></div>
<script>
/*
点击按钮后,读取css的样式
*/
const btn = document.getElementById("btn")
// querySelector方法:选中页面中出现的第一个标签
const box1 = document.querySelector(".box1")
// 点击按钮触发的函数
btn.onclick = function() {
// 不会用这种方式来读取样式
// console.log(box1.style.width)
/*
getComputedStyle()
-它会返回一个对象,这个对象中包含了当前元素的所有生效的样式
- 获取具体的样式数值:对象.width 获取样式的宽度
- 伪元素获取样式信息:getComputedStyle(要获取的样式对象, "要获取的为元素")
宽度以及高度的计算:
- 一般通过: "对象.width" 读取样式宽度时,都是带宽度的
- 通过 parseInt(对象.width)将 200px 中的px消除
- 再通过 + "px" 的方式加上单位
返回值
- 返回的一个对象,对象中存储了当前元素的样式
注意
- 样式对象中返回的样式值,不一定能拿来直接计算,有可能是auto
所以使用时,一定要确保值偶是可以计算的才去计算
*/
const styleObj = getComputedStyle(box1)
// 获取为元素的样式信息
const beforeObj = getComputedStyle(box1, "before")
// 通过 parseInt(对象.width)将 200px 中的px消除
// 再通过 + "px" 的方式加上单位
parseInt(styleObj.width) + 100 + "px"
// 获取元素的样式
console.log(styleObj.width)
}
</script>
</body>
一五三、JavaScript——通过属性读取样式
元素.clientHeight
元素.clientWidth
- 获取元素内部的宽度和高度(包括内容区和内边距,width和padding)
- 返回的结果就是纯数字,不带单位
元素.offsetHeight
元素.offsetWidth
- 获取元素的可见框的大小(包括内容区、内边距和边框)
- 返回的结果就是纯数字,不带单位
元素.scrollHeight
元素.scrollWidth
- 获取元素滚动区域的大小
元素.offsetParent
- 获取元素定位的父元素
- 定位父元素,离当前元素最近的开启了定位的祖先元素
如果所有的元素都没有开启定位则返回body
元素.offsetTop
元素.offsetLeft
- 获取元素相对于起定位父元素的偏移量
<style>
#box1 {
width: 200px;
height: 200px;
padding: 50px;
margin: 50px;
border: 10px red solid;
background-color:aqua;
/* 设置多余的部分溢出, */
overflow: auto;
}
#box2 {
width: 100px;
height: 500px;
background-color:chartreuse;
}
</style>
</head>
<body>
<button id="btn">点我一下</button>
<hr>
<div id="box1">
<div id="box2"></div>
</div>
<script>
const btn = document.getElementById("btn")
const box1 = document.getElementById("box1")
btn.onclick = function() {
/*
元素.clientHeight
元素.clientWidth
- 获取元素内部的宽度和高度(包括内容区和内边距,width和padding)
- 返回的结果就是纯数字,不带单位
元素.offsetHeight
元素.offsetWidth
- 获取元素的可见框的大小(包括内容区、内边距和边框)
- 返回的结果就是纯数字,不带单位
元素.scrollHeight
元素.scrollWidth
- 获取元素滚动区域的大小
元素.offsetParent
- 获取元素定位的父元素
- 定位父元素,离当前元素最近的开启了定位的祖先元素
如果所有的元素都没有开启定位则返回body
元素.offsetTop
元素.offsetLeft
- 获取元素相对于起定位父元素的偏移量
*/
}
console.log(box1.clientWidth)
</script>
</body>
一五四、JavaScript——操作class
- 元素.classList.add(class名称,class名称) :向元素中添加一个或多个class
元素.classList.remove(class名称) :删除一个或多个class
元素.classList.toggle(class名称) :切换class
元素.classList.replace(class1, class2) :1去掉class1,替换成class2
box1.classList.contains("box1"): 判断是否含有某个class
<body>
<button id="btn">点我一下</button>
<hr />
<div class="box1"></div>
<script>
const btn = document.getElementById("btn")
// querySelector取网页中第一次出现的标签
const box1 = document.querySelector(".box1")
btn.onclick = function() {
/*
除了直接修改样式外,也可以通过修改class属性来简介修改样式
被替换的.className += " 具体替换的"
注意具体替换的前有空格
box1.className += " box2"
*/
// box1.className += " box2"
/*
元素.classList.add(class名称,class名称) :向元素中添加一个或多个class
元素.classList.remove(class名称) :删除一个或多个class
元素.classList.toggle(class名称) :切换class
元素.classList.replace(class1, class2) :1去掉class1,替换成class2
box1.classList.contains("box1"): 判断是否含有某个class
*/
// 元素.classList 是一个对象,对象中提供了对当前元素的类的各种操作方法
box1.classList.add(box2)
box1.classList.remove(box2)
box1.classList.toggle("box2")
// 把1去掉替换成2
box1.classList.replace("box1","box2")
// 检查是否包含
box1.classList.contains("box1")
}
</script>
</body>
一五五、JavaScript——事件对象简介
event 事件
- 事件对象
- 事件对象是由浏览器在事件触发时所创建的对象
这个对象中封装了事件相关的各种信息
- 通过事件对象可以获取到事件的详细信息
比如:鼠标的坐标,键盘的按键
- 浏览器在创建事件对象后,会将事件作为响应函数的参数传递
所以我们可以在事件的回调函数中定义一个形参来接收事件对象
<style>
#box1 {
width: 300px;
height: 300px;
border: 10px greenyellow solid;
}
</style>
</head>
<body>
<div id="box1"></div>
<script>
/*
event 事件
- 事件对象
- 事件对象是由浏览器在事件触发时所创建的对象
这个对象中封装了事件相关的各种信息
- 通过事件对象可以获取到事件的详细信息
比如:鼠标的坐标,键盘的按键
- 浏览器在创建事件对象后,会将事件作为响应函数的参数传递
所以我们可以在事件的回调函数中定义一个形参来接收事件对象
*/
// onmousemove鼠标移动事件
// box1.onmousemove = function() {
// console.log("鼠标移动了")
// }
// 方式1:回调函数传入参数用来记录
// box1.onmousemove = function(event) {
// console.log(event)
// }
// 方式2:匿名函数传入形参命名为event
// box1.onmousemove = event => {
// console.log(event)
// }
const box1 = document.getElementById("box1")
// addEventListener("事件", 函数)
box1.addEventListener("mousemove", event => {
// console.log(event)
// 打印鼠标的坐标
console.log(event.clientX, event.clientY)
// 让鼠标坐标显示在网页中
box1.textContent = event.clientX + "," +event.clientY
})
</script>
</body>
一五六、JavaScript——event对象
MDN前端参考文档:Event - Web APIs | MDN (mozilla.org)
在DOM中存在着多种不同类型的事件对象
- 多种事件对象有一个共同的祖先 Event
- event.target 触发事件的对象
- event,currentTarget 绑定事件的对象(问this)
- event.stopPropaggation() 停止事件的向上传导
- event.preventDefault() 取消默认行为
- 事件的冒泡(bubble)
- 事件的冒泡就是指事件的向上传导
- 当元素的某个事件被触发后,其祖先元素上的相同元素也会被触发
- 冒泡的存在大大简化了代码的编写,但在一些场景下我们并不希望冒泡存在
<style>
#box1 {
width: 300px;
height: 300px;
background-color: antiquewhite;
}
</style>
</head>
<body>
<div id="box1"></div>
<script>
/*
在DOM中存在着多种不同类型的事件对象
- 多种事件对象有一个共同的祖先 Event
- event.target 触发事件的对象
- event,currentTarget 绑定事件的对象(问this)
- event.stopPropaggation() 停止事件的向上传导
- event.preventDefault() 取消默认行为
- 事件的冒泡(bubble)
- 事件的冒泡就是指事件的向上传导
- 当元素的某个事件被触发后,其祖先元素上的相同元素也会被触发
- 冒泡的存在大大简化了代码的编写,但在一些场景下我们并不希望冒泡存在
*/
// 获取box1
const box1 = document.getElementById("box1")
// addEventListener("事件", "函数")
box1.addEventListener("click", event => {
// alert(event)
// console.log(event)
/*
在事件的响应函数中:
event.target 表示的是触发事件的对象,由谁引发的事件就显示谁
*/
// 打印 <div id="box1"></div>;因为是由于box1触发的
console.log(event.target)
})
</script>
</body>
一五七、JavaScript——事件的冒泡
<style>
#box1{
width: 100px;
height: 100px;
background-color: cornflowerblue;
border-radius: 50%;
position: absolute;
}
#box2{
width: 500px;
height: 500px;
background-color: coral;
}
#box3{
width: 200px;
height: 200px;
background-color: aqua;
}
#box4{
width: 100px;
height: 100px;
background-color: brown;
}
</style>
</head>
<body>
<div id="box1"></div>
<!-- 创建一个box2 -->
<div id="box2"></div>
<div id="box3" onclick="alert(3)">
<div id="box4" onclick="alert(4)"></div>
</div>
<script>
/*
使小绿球可以跟鼠标一起移动
事件的冒泡和元素的样式无关,只和结构有关
*/
const box1 = document.getElementById("box1")
const box2 = document.getElementById("box2")
// 绑定鼠标移动事件,并传入形参event
// 并且绑定在整个界面上,而不是box1上
document.addEventListener("mousemove", (event) => {
// console.log(111)
// 图标跟随鼠标移动
box1.style.left = event.x + "px"
box1.style.top = event.y + "px"
})
// 取消box2的事件的冒泡
box2.addEventListener("mousemove", (event) => {
// 取消事件的冒泡,这样再box2的区域小球就不会随着鼠标移动
event.stopPropagation()
})
</script>
</body>
一五八、JavaScript——事件的委派
<body>
<button id="btn">点我一下</button>
<hr>
<ul id="list">
<li><a href="javascript:;">链接1</a></li>
<li><a href="javascript:;">链接2</a></li>
<li><a href="javascript:;">链接3</a></li>
<li><a href="javascript:;">链接4</a></li>
</ul>
<script>
// 获取所有为ul标签中的a标签
const links = document.querySelectorAll("ul a")
// 获取list标签
const list = document.getElementById("list")
const btn = document.getElementById("btn")
for(let i=0; i<links.length; i++) {
links[i].addEventListener("click", event => {
alert(event.target.textContent)
})
}
// 点击按钮后,在ul中新增一个li
btn.addEventListener("click", () => {
// 通过insertAdjacentHTML("插入的位置", "插入的内容") 直接插入标签
list.insertAdjacentHTML("beforeend", "<li><a href='javascript:;'>新超链接</a></li>")
})
/*
上面虽然实现了点击按钮新增链接的功能,但还经历了遍历和点击添加的,
我一个希望
只绑定一次事件,即可以让所有的超链接,包括当下和未来的超链接都具有这些事情
思路:
可以将事件统一绑定给document,这样点击超链接时由于事件的冒泡
会导致document上的点击事件被触发,这样只绑定依次,所有的超链接都会具有这些事件
委派就是将本该绑定多个元素的的事件,统一绑定给一个共同事件
*/
// 获取list中的所有链接
const linkes = list.getElementsByTagName("a")
// 将点击事件扩大到整个网页,即对象是document
document.addEventListener("click", (event) => {
// 在执行代码前,判断一下事件是由谁来触发
// 检查event.target 是否在 links 中存在
// 但link打印出来是 "HTMLCollection [a,a,a,a]" 我们需要的是数组
// 调用静态方法 Arrary.form(linkes) 后,数组变为[a,a,a,a]
// 或者直接用展开运算符展开[...linkes] 效果是一样的
// 判断如果触发事件在linkes中出现了
if([...links].includes(event.target)) {
// 点击事件触发后显示触发的文本
alert(event.target.textContent)
}
})
</script>
</body>
一六零、JavaScript——事件的捕获
事件的传播机制:
- 在DOM中,事件的传播可以分为三个阶段:
1.捕获阶段 (由祖先元素向目标元素进行事件的捕获)(默认情况下,事件不会在捕获阶段触发)
2.目标阶段 (触发事件的对象)
3.冒泡阶段 (由目标元素向祖先元素的进行事件的冒泡)
- 事件的捕获,指事件从外向内的传导
捕获是从外向里捕获
冒泡是由里向外捕获
当我们当前元素的触发事件以后,会先从当前元素的最大祖先元素开始事件的捕获
- 如果希望在捕获阶段触发事件,可以将addEventListener的第三个参数设置为true
一般情况下我们不希望事件在捕获阶段触发,所以通常不需要设置addEventListener第三个参数为true
eventPhase 表示事件触发的阶段,结果是数字
1 表示捕获阶段 2 表示目标阶段 3 表示冒泡阶段
<style>
#box1 {
width: 300px;
height: 300px;
background-color: aquamarine;
}
#box2 {
width: 200px;
height: 200px;
background-color:crimson
}
#box3 {
width: 100px;
height: 100px;
background-color:darkblue;
}
</style>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3">
</div>
</div>
</div>
<script>
/*
事件的传播机制:
- 在DOM中,事件的传播可以分为三个阶段:
1.捕获阶段 (由祖先元素向目标元素进行事件的捕获)(默认情况下,事件不会在捕获阶段触发)
2.目标阶段 (触发事件的对象)
3.冒泡阶段 (由目标元素向祖先元素的进行事件的冒泡)
- 事件的捕获,指事件从外向内的传导
捕获是从外向里捕获
冒泡是由里向外捕获
当我们当前元素的触发事件以后,会先从当前元素的最大祖先元素开始事件的捕获
- 如果希望在捕获阶段触发事件,可以将addEventListener的第三个参数设置为true
一般情况下我们不希望事件在捕获阶段触发,所以通常不需要设置addEventListener第三个参数为true
eventPhase 表示事件触发的阶段,结果是数字
1 表示捕获阶段 2 表示目标阶段 3 表示冒泡阶段
*/
const box1 = document.getElementById("box1")
const box2 = document.getElementById("box2")
const box3 = document.getElementById("box3")
box1.addEventListener("click", event => {
alert(event.eventPhase) //eventPhase 表示事件触发的阶段
},true)
box2.addEventListener("click", event => {
alert(2)
})
box3.addEventListener("click", event => {
alert(3)
})
</script>
</body>
一六一、JavaScript——BOM简介
BOM
- 浏览器对象模型
- BOM为我们提供了一组对象,通过这组对象可以完成对浏览器的各种操作
- BOM对象
- Window —— 代表浏览器窗口(全局对象)
- Navigator —— 浏览器的对象(可以用来识别浏览器)
- Location —— 浏览器的地址栏信息
- History —— 浏览器的历史记录(控制浏览器前进后退)
- Screen —— 屏幕的信息
- BOM对象是作为window对象的属性保存的,所以可以直接在JS中访问这些对象
一六二、JavaScript——Navigator
- BOM对象
- MDN前端参考文档:https://developer.mozilla.org/en-US/docs/Web/API/Navigator
- Navigator —— 浏览器的对象(可以用来识别浏览器)
userAgent 返回一个用来描述浏览器信息的字符串
<body>
<script>
/*
- BOM对象
- MDN前端参考文档:https://developer.mozilla.org/en-US/docs/Web/API/Navigator
- Navigator —— 浏览器的对象(可以用来识别浏览器)
userAgent 返回一个用来描述浏览器信息的字符串
*/
// console.log(navigator.userAgent)
function getBrowserName(userAgent) {
// The order matters here, and this may report false positives for unlisted browsers.
if (userAgent.includes("Firefox")) {
// "Mozilla/5.0 (X11; Linux i686; rv:104.0) Gecko/20100101 Firefox/104.0"
return "Mozilla Firefox";
} else if (userAgent.includes("SamsungBrowser")) {
// "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.4 Chrome/67.0.3396.87 Mobile Safari/537.36"
return "Samsung Internet";
} else if (userAgent.includes("Opera") || userAgent.includes("OPR")) {
// "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_5_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36 OPR/90.0.4480.54"
return "Opera";
} else if (userAgent.includes("Edge")) {
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"
return "Microsoft Edge (Legacy)";
} else if (userAgent.includes("Edg")) {
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36 Edg/104.0.1293.70"
return "Microsoft Edge (Chromium)";
} else if (userAgent.includes("Chrome")) {
// "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
return "Google Chrome or Chromium";
} else if (userAgent.includes("Safari")) {
// "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Mobile/15E148 Safari/604.1"
return "Apple Safari";
} else {
return "unknown";
}
}
const browserName = getBrowserName(navigator.userAgent);
console.log(`You are using: ${browserName}`);
</script>
</body>
一六三、JavaScript——Location
location表示的是网站的地址栏的信息
- 可以直接将location的值修改为一个新的地址,这样会使得网页发生跳转
- location.assign() 跳转到一个新的地址 (可以通过回退按钮回退到原来的地址)
- location.replac() 跳转到一个新的地址 (无法通过回退按钮回退到原来的地址)
- location.reload() 刷新页面,可以传递一个true来强制清缓存刷新
- location.replac() 跳转到一个新的地址 (无法通过回退按钮回退到原来的地址)
- location.href 获取当前地址
一六四、JavaScript——History
MDN前端文档:https://developer.mozilla.org/en-US/docs/Web/API/History
history.back() 浏览器回退
history.forward() 浏览器前进
history.go() 可以向前跳转也可以向后跳转,取决于括号中输入的数字,正数向前,负数向后
<body>
<button id="btn">点我一下</button>
<script>
const btn = document.getElement("btn")
btn.onclick = () => {
/*
history.back() 浏览器回退
istory.forward() 浏览器前进
history.go() 可以向前跳转也可以向后跳转,取决于括号中输入的数字,正数向前,负数向后
*/
// 后退
history.back()
// 前进
history.forward()
//
history.go()
}
</script>
</body>
一六五、JavaScript——定时器
通过定时器,可以是代码再指定时间后执行
- 设置定时器打方式有两种:
setTimeout() (只执行一次)
- 参数
1. 回调函数(要执行的代码)
2. 间隔的时间(毫秒)
clearTimeout()
- 关闭定时器
setInterval() (每隔一段时间就会执行依次)
- 参数:
1. 回调函数(要执行的代码)
2. 间隔的时间(毫秒)
clearInterval()
- 关闭定时器
<body>
<h1 id="num"></h1>
<script>
/*
通过定时器,可以是代码再指定时间后执行
- 设置定时器打方式有两种:
setTimeout() (只执行一次)
- 参数
1. 回调函数(要执行的代码)
2. 间隔的时间(毫秒)
clearTimeout()
- 关闭定时器
setInterval() (每隔一段时间就会执行依次)、
- 参数:
1. 回调函数(要执行的代码)
2. 间隔的时间(毫秒)
clearInterval()
- 关闭定时器
*/
const timer = setTimeout(() => {
alert("我是定时器中的代码")
},1000)
// 关闭定时器
clearTimeout(timer)
const numH1 = document.getElementById("num")
let num = 0
// 构建一个定时器,在指定时间不断生成数字并显示在H1标签中
const timeres = setInterval(() => {
num++
numH1.textContent = num
// 判断如果定时器的数字到200,则关闭定时器
if(num === 200) {
clearInterval(timeres)
}
},500)
</script>
</body>
一六六、JavaScript——调用栈
时间循环(event loop)
- 函数在每次执行时,都会产生一个执行环境
- 执行环境负责存储函数执行的一切数据
- 问题:函数的执行环境要存储到哪里
- 函数执行环境存储到了一个叫做调用栈的地方
- 栈,是一种数据结构,特点:后进先出
调用栈(call stack)
- 调用栈负责存储函数的执行环境
- 当一个函数被调用时,它的执行环境会作为一个栈帧
插入到调用栈的栈项,函数执行完毕其他栈会自动从栈中弹出
调用栈中放的都是正在执行的函数
<script>
/*
时间循环(event loop)
- 函数在每次执行时,都会产生一个执行环境
- 执行环境负责存储函数执行的一切数据
- 问题:函数的执行环境要存储到哪里
- 函数执行环境存储到了一个叫做调用栈的地方
- 栈,是一种数据结构,特点:后进先出
调用栈(call stack)
- 调用栈负责存储函数的执行环境
- 当一个函数被调用时,它的执行环境会作为一个栈帧
插入到调用栈的栈项,函数执行完毕其他栈会自动从栈中弹出
调用栈中放的都是正在执行的函数
*/
function fn(){
let a = 10;
let b = 20;
}
</script>
一六七、JavaScript——消息队列
消息队列
- 队列,是一种数据结构, 特点:先进先出
- 当我们触发一个事件时,其响应函数并不是直接就添加到调用栈中的
因为调用栈中又可能会存在一些还没有执行完的代码
- 事件触发后,JS引擎是将事件响应函数插入到消息队列中排队
<script>
/*
时间循环(event loop)
- 函数在每次执行时,都会产生一个执行环境
- 执行环境负责存储函数执行的一切数据
- 问题:函数的执行环境要存储到哪里
- 函数执行环境存储到了一个叫做调用栈的地方
- 栈,是一种数据结构,特点:后进先出
调用栈(call stack)
- 调用栈负责存储函数的执行环境
- 当一个函数被调用时,它的执行环境会作为一个栈帧
插入到调用栈的栈项,函数执行完毕其他栈会自动从栈中弹出
调用栈中放的都是正在执行的函数
消息队列
- 队列,是一种数据结构, 特点:先进先出
- 当我们触发一个事件时,其响应函数并不是直接就添加到调用栈中的
因为调用栈中又可能会存在一些还没有执行完的代码
- 事件触发后,JS引擎是将事件响应函数插入到消息队列中排队
*/
function fn() {
let a = 10
let b = 20
function fn2() {
console.log("fn2")
}
fn2()
console.log("fn!")
}
fn()
console.log(1111)
const btn = document.getElementById("btn")
btn.onclick = function() {
console.log("按钮被点击了")
}
</script>