API学习02
事件流
事件流指的是事件完整执行过程中的流动路径
事件流的两个阶段
事件捕获
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.father {
width: 500px;
height: 500px;
background-color: pink;
}
.son {
width: 200px;
height: 200px;
background-color: purple;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
// 进行捕获后,点击son的div :弹窗顺序 body - father - son
document.addEventListener('click',function (){
alert('我是爷爷')
},true)
const father = document.querySelector('.father')
father.addEventListener('click',function (){
alert('我是爸爸')
},true)
const son = document.querySelector('.son')
son.addEventListener('click',function (){
alert('我是儿子')
},true)
</script>
</body>
</html>
事件冒泡
阻止冒泡
比如在登陆时,只填写用户名未填写密码时不应该提交登录,又或者在填写一些个人信息时必填项未填完时不能进行下一步操作
事件解绑
在之前绑定事件时是用on事件方式,直接使用null覆盖就能实现解绑
addEventListenner解绑
两种鼠标经过事件区别:
mouseover 和 mouseout 会有冒泡效果 ,父元素有鼠标事件,子元素没有时,在从父元素进入子元素时会先触发父元素的鼠标离开,又会冒泡执行父元素的鼠标经过事件
mouseenter 和 mouseleave 没有冒泡效果 (推荐)
两种监听的区别
**传统on注册(L0): **
同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
直接使用null覆盖偶就可以实现事件的解绑
都是冒泡阶段执行的
事件监听注册(L2)
语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
后面注册的事件不会覆盖前面注册的事件(同一个事件)
可以通过第三个参数去确定是在冒泡或者捕获阶段执行
必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
匿名函数无法被解绑
事件委托
事件委托实现tab栏切换
实现效果和API-01中案例是相似的,只是使用了不同方式
<body>
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<li><a class="active" href="javascript:" data-id="0">精选</a></li>
<li><a href="javascript:" data-id="1">美食</a></li>
<li><a href="javascript:" data-id="2">百货</a></li>
<li><a href="javascript:" data-id="3">个护</a></li>
<li><a href="javascript:" data-id="4">预告</a></li>
</ul>
</div>
<div class="tab-content">
<div class="item active"><img src="../img/tab00.png" alt=""/></div>
<div class="item"><img src="../img/tab01.png" alt=""/></div>
<div class="item"><img src="../img/tab02.png" alt=""/></div>
<div class="item"><img src="../img/tab03.png" alt=""/></div>
<div class="item"><img src="../img/tab04.png" alt=""/></div>
</div>
</div>
<script>
// 1. 获取元素
const ul = document.querySelector('.tab-nav ul')
// 2. 点击事件
ul.addEventListener('click', function (e) {
if (e.target.tagName === 'A') {
document.querySelector('.tab-nav .active').classList.remove('active')
e.target.classList.add('active')
document.querySelector('.tab-content .active').classList.remove('active')
// 字符串要进行转换
const id = parseInt(e.target.dataset.id)
// (1)方法一
// document.querySelector(`.tab-content .item:nth-child(${id + 1})`).classList.add('active')
// (2)方法二
const items = document.querySelectorAll('.tab-content .item')
items[id].classList.add('active')
}
})
</script>
</body>
一些其他事件
页面加载事件
- 页面资源全部加载完成
-
HTMl文档加载完成
比如有时浏览网页时只显示出了页面结构,而图片未加载完成
元素滚动事件
scrollLeft和scrollTop (属性):获取移动(左右、上下)的距离,这两个属性的值是可读可写的,尽量在scroll事件中使用,得到的是数字,没有单位
获取页面滚动:document.documentElement.scrollTop
document.documentElement获取的是html元素
scrollTo() 方法:可把内容滚动到指定的坐标
d2eceacfe40bf94b7d32e72227942.png#pic_center)
页面尺寸事件
clientWidtn和clientHeight
虽然我们可以计算尺寸和距离,但是如果每次修改盒子大小都会引起尺寸的变化,所以如果页面可以js的方式,计算元素在页面中的位置会方便很多
offsetWidth等
注意:这两个属性受父级元素的影响,计算的是距离目标元素的带有定位的祖先元素的距离
其他获取尺寸
相对于视口,拖拉滚动条,位置在视口中发生变化,尺寸也会发生变化
几种获取尺寸区别
日期对象
-
日期对象是用来表示时间的对象,可以得到当前系统时间
-
日期对象的实例化:const date = new Date()
没有参数得到的是当前时间,可以传入参数来指定时间,参数是字符串!
日期对象的方法
要先实例化,再调用方法!!!
要注意月份的返回值是从0开始的,要获得匹配的月份需要对返回的数值进行加一操作
获取星期几时,返回0代表的是周日
怎么让时间以 YYYY-MM-DD HH-mm形式出现呢?
<script>
const date = new Date('2024-3-8 8:30:50')
function getTime(date){
const y = date.getFullYear()
const mon = date.getMonth() + 1 > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1)
const d = date.getDate() > 10 ? date.getDate() : '0' + date.getDate()
const h = date.getHours() > 9 ? date.getHours() : '0' + date.getHours()
const minutes = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes()
const s = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds()
return y + '-' + mon + '-' + d + ' ' + h + ':' + minutes + ':' + s
}
console.log(getTime(date))
// 如何让时间一直显示当前时间
// 回调函数会有延迟
setInterval(function (){
const div = document.querySelector('div')
const date1 = new Date()
div.innerHTML = getTime(date1)
},1000)
</script>
date对象也提供了一些方法帮助快速生成格式化的时间
<script>
const date = new Date()
console.log(date.toDateString()) // Tue Mar 26 2024
console.log(date.toTimeString()) // 16:40:05 GMT+0800 (中国标准时间)
console.log(date.toLocaleString()) // 2024/3/26 下午4:40:23
console.log(date.toLocaleTimeString()) // 下午4:40:45
console.log(date.toLocaleDateString()) // 2024/3/26
</script>
时间戳
上面的图片来自b站pink老师资料,我测试时发现使用1970-01-01 00:00:00时,时间戳是负数,之后进行调试,发现时间戳的起点应该是1970-01-01 08:00:00
查阅时看到这么一句话:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的
总秒数
。13位说明精度是毫秒,10位说明精度是秒。
获取时间戳
<script>
// 1. getTime() 必须实例化
const date = new Date()
console.log(date.getTime())
// 2. +new Date() 字符串转数字
console.log(+new Date())
// 3. Date.now()
console.log(Date.now())
</script>
第三种只能获得当前的时间戳,第一种和第二种可以传参数获得指定时间的时间戳,推荐使用第二种方式
时间戳-倒计时案例
需求:计算下课倒计时
分析:
①:用将来时间减去现在时间就是剩余的时间
②:核心: 使用将来的时间戳减去现在的时间戳
③:把剩余的时间转换为 天 时 分 秒
注意:
通过时间戳得到是毫秒,需要转换为秒在计算
转换公式:
d = parseInt(总秒数/ 60/60 /24); // 计算天数
h = parseInt(总秒数/ 60/60 %24) // 计算小时
m = parseInt(总秒数 /60 %60 ); // 计算分数
s = parseInt(总秒数%60); // 计算当前秒数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.countdown {
width: 240px;
height: 305px;
text-align: center;
line-height: 1;
color: #fff;
background-color: brown;
/* background-size: 240px; */
/* float: left; */
overflow: hidden;
}
.countdown .next {
font-size: 16px;
margin: 25px 0 14px;
}
.countdown .title {
font-size: 33px;
}
.countdown .tips {
margin-top: 80px;
font-size: 23px;
}
.countdown small {
font-size: 17px;
}
.countdown .clock {
width: 142px;
margin: 18px auto 0;
overflow: hidden;
}
.countdown .clock span,
.countdown .clock i {
display: block;
text-align: center;
line-height: 34px;
font-size: 23px;
float: left;
}
.countdown .clock span {
width: 34px;
height: 34px;
border-radius: 2px;
background-color: #303430;
}
.countdown .clock i {
width: 20px;
font-style: normal;
}
</style>
</head>
<body>
<div class="countdown">
<p class="next">今天是2222年2月22日</p>
<p class="title">下课倒计时</p>
<p class="clock">
<span id="hour">00</span>
<i>:</i>
<span id="minutes">25</span>
<i>:</i>
<span id="second">20</span>
</p>
<p class="tips">20:00:00下课倒计时</p>
</div>
<script>
const hour = document.querySelector('#hour')
const minutes = document.querySelector('#minutes')
const second = document.querySelector('#second')
function getTime(){
// 1. 得到现在的时间戳
const now = +new Date()
// 2. 得到参考的时间戳
const future = +new Date('2024-3-26 20:00:00')
// 3. 相减并先转换成秒数
const t = (future - now) / 1000
console.log(t)
// 用let 因为要进行补0
// 计算公式:计算时分秒
// 小时: h = parseInt(总秒数 / 60 / 60 % 24)
// 分钟: m = parseInt(总秒数 / 60 % 60 )
// 秒数: s = parseInt(总秒数 % 60)
let h = Math.round(t / 60 / 60 % 24)
let m = Math.round(t / 60 % 60)
let s = Math.round(t % 60)
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
// console.log(h)
// console.log(m)
// console.log(s)
hour.innerHTML = h
minutes.innerHTML = m
second.innerHTML = s
}
const next = document.querySelector('.next')
next.innerHTML = new Date().toLocaleDateString()
// 解决延迟渲染
getTime()
// 定时器函数的执行函数不需要加括号
setInterval(getTime,1000)
</script>
</body>
</html>
页面效果
只是展示了静态效果图,实际数字是动态变化的