目录
获取位置-scrollLeft和scrollTop(属性):
二,APIs
3.定时器-间歇函数
3.1开启定时器
setInterval(函数,时间间隔)
作用:每隔一段时间调用这个函数
间隔时间单位是毫秒
<script>
//方法一
setInterval(function(){
console.log('一秒打印一次')
},1000)
//方法二
function fn(){
console.log('一秒打印一次')
}
setInterval(fn,1000)
</script>
3.2关闭定时器
let 变量名 = setInterval(函数,间隔时间)
clearInterval(变量名)
function fn(){
console.log('一秒打印一次')
}
let n = setInterval(fn,1000)
//关闭定时器
clearInterval(n)
阅读注册协议倒计时:
需求:按钮60秒之后才可以使用
分析:
1.一开始先把按钮禁用(disabled属性)
2.一定要获取元素
3.函数内处理逻辑
- 秒数开始减减
- 按钮里面的文字跟着一起变化
- 如果秒数等于0 停止定时器 里面文字变为 同意 后按钮可以点击
<body>
<textarea>
1.一开始先把按钮禁用(disabled属性)
2.一定要获取元素
3.函数内处理逻辑
</textarea>
<br>
<button >已经阅读用户协议(10秒)</button>
<script>
const button = document.querySelector('button')
//禁用按钮
button.disabled = true
//这里一定要用let 倒计时
let i = 10
let n = setInterval(function(){
i--
button.innerHTML = `已经阅读用户协议(${i}秒)`
if (i === 0){
clearInterval(n)
button.innerHTML = `同意`
button.disabled = false
}
},1000)
</script>
</body>
案例:轮播图定时版
需求:每隔一秒钟切换一个图片
分析:
1.准备一个数组对象,里面包含详细信息
2.获取元素
3.设置定时函数
- 设置一个变量++
- 找到变量对应的对象
- 更改图片,文字信息
- 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
4.处理图片自动复原从头播放(放到变量++后面,紧挨)
- 如果图片播放到最后一张,就是大于等于数组的长度
- 则把变量重置为0
<!DOCTYPE html>
<html lang="en">
<head>
<title>轮播图点击切换</title>
<style>
* {
box-sizing: border-box;
}
.slider {
width: 560px;
height: 400px;
overflow: hidden;
}
.slider-wrapper {
width: 100%;
height: 320px;
}
.slider-wrapper img {
width: 100%;
height: 100%;
display: block;
}
.slider-footer {
height: 80px;
background-color: rgb(100, 67, 68);
padding: 12px 12px 0 12px;
position: relative;
}
.slider-footer .toggle {
position: absolute;
right: 0;
top: 12px;
display: flex;
}
.slider-footer .toggle button {
margin-right: 12px;
width: 28px;
height: 28px;
appearance: none;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.slider-footer .toggle button:hover {
background: rgba(255, 255, 255, 0.2);
}
.slider-footer p {
margin: 0;
color: #fff;
font-size: 18px;
margin-bottom: 10px;
}
.slider-indicator {
margin: 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
}
.slider-indicator li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background: #fff;
opacity: 0.4;
cursor: pointer;
}
.slider-indicator li.active {
width: 12px;
height: 12px;
opacity: 1;
}
</style>
</head>
<body>
<div class="slider">
<div class="slider-wrapper">
<img src="./slider01.jpg" alt="" />
</div>
<div class="slider-footer">
<p>对人类来说会不会太超前了?</p>
<ul class="slider-indicator">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="toggle">
<button class="prev"><</button>
<button class="next">></button>
</div>
</div>
</div>
<script>
// 1. 初始数据
const sliderData = [
{ url: './slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },
{ url: './slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },
{ url: './slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },
{ url: './slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },
{ url: './slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },
{ url: './slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },
{ url: './slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },
{ url: './slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },
]
//2.获取元素
let i = 0
//3.设置定时器
setInterval(function () {
i++
//无缝衔接位置
if(i >= sliderData.length){
i =0
}
//更改图片
const img = document.querySelector('.slider-wrapper img')
img.src = sliderData[i].url
//更改标题
const p = document.querySelector('.slider-footer p')
p.innerHTML = sliderData[i].title
//删除前一个小圆点
const activeClass = document.querySelector('.slider-footer .slider-indicator .active')
activeClass.classList.remove('active')
//激活小圆点
const li = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`)
li.classList.add('active')
}, 1000)
</script>
</body>
</html>
4.事件监听
目标:能够给DOM元素添加事件监听
什么是事件?
事件是在编程时系统内发生的动作或者发生的事情
比如用户在网页上单击一个按钮
什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为绑定事件或者注册事件,比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等
语法:
元素对象.addEventListener('事件类型',要执行的函数)
事件监听三要素:
- 事件源:那个DOM元素被事件触发了,要获取DOM元素
- 事件类型:用什么方式触发,比如鼠标单击click,鼠标经过mouseover等
- 事件调用的函数:要做什么事
举例说明:
//1.事件类型要加引号
//2.函数是点击之后再去执行,每次点击都会执行一次
<body>
<button>按钮</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener ('click',function(){
console.log('点击')
})
</script>
</body>
京东点击关闭顶部广告:
<head>
<style>
.box {
position: relative;
width: 1000px;
height: 200px;
background-color: pink;
margin: 100px auto;
text-align: center;
font-size: 50px;
line-height: 200px;
font-weight: 700;
}
.box1 {
position: absolute;
right: 20px;
top: 10px;
width: 20px;
height: 20px;
background-color: skyblue;
text-align: center;
line-height: 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
我是广告
<div class="box1">X</div>
</div>
<script>
// 1. 获取事件源
const box1 = document.querySelector('.box1')
// 关闭的是大盒子
const box = document.querySelector('.box')
// 2. 事件侦听
box1.addEventListener('click', function () {
box.style.display = 'none'
})
</script>
</body>
随机点名案例:
分析:
点击开始按钮随机抽取数组的一个数据,放到页面中
点击结束按钮删除数组当前抽中的一个数据
当抽取到最后一个数据的时候,两个按钮同时禁用(写点开始里面,只剩最后一个数据不用抽了)
核心:利用定时器快速展示,停止定时器结束展示
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* {
margin: 0;
padding: 0;
}
h2 {
text-align: center;
}
.box {
width: 600px;
margin: 50px auto;
display: flex;
font-size: 25px;
line-height: 40px;
}
.qs {
width: 450px;
height: 40px;
color: red;
}
.btns {
text-align: center;
}
.btns button {
width: 120px;
height: 35px;
margin: 0 50px;
}
</style>
</head>
<body>
<h2>随机点名</h2>
<div class="box">
<span>名字是:</span>
<div class="qs">这里显示姓名</div>
</div>
<div class="btns">
<button class="start">开始</button>
<button class="end">结束</button>
</div>
<script>
// 数据数组
const arr = ['马超', '黄忠', '赵云', '关羽', '张飞']
//点击开始按钮随机抽取的一个数组放到页面中
const qs = document.querySelector('.qs')
const start = document.querySelector('.start')
let timerId = 0
//随机号也要全局变量
let random = 0
start.addEventListener('click', function () {
//设置定时器快速刷新
//将timerId设置为全局变量,在下面关闭定时器时才能使用
timerId = setInterval(function () {
random = Math.floor(Math.random() * arr.length)
qs.innerHTML = arr[random]
console.log(arr[random])
}, 35)
//如果数组里面只有一个值了,还需要抽取吗?不需要 让两个按钮禁用就可以
if(arr.length === 1){
start.disabled = true
end.disabled = true
}
})
//点击结束按钮删除数组当中的一个数据
const end = document.querySelector('.end')
end.addEventListener('click', function () {
clearInterval(timerId)
arr.splice(random, 1)
})
</script>
</body>
</html>
拓展-事件监听版本:
- DOM L0
事件源.on事件= function() {}
- DOM L2
事件源.addEventListener(事件,事件处理函数)
- 区别
on方式会被覆盖,addEventListener方式可绑定多次,拥有事件更多特性,推荐使用
4.1事件类型:
鼠标事件:轮播图点击切换
分析:
- 右侧按钮点击,变量++,如果大于等于8,则复原0
- 左侧按钮点击,变量--,如果小于0,则复原最后一张
- 鼠标经过暂停定时
- 鼠标离开开启定时
<!DOCTYPE html>
<html lang="en">
<head>
<title>轮播图点击切换</title>
<style>
* {
box-sizing: border-box;
}
.slider {
width: 560px;
height: 400px;
overflow: hidden;
}
.slider-wrapper {
width: 100%;
height: 320px;
}
.slider-wrapper img {
width: 100%;
height: 100%;
display: block;
}
.slider-footer {
height: 80px;
background-color: rgb(100, 67, 68);
padding: 12px 12px 0 12px;
position: relative;
}
.slider-footer .toggle {
position: absolute;
right: 0;
top: 12px;
display: flex;
}
.slider-footer .toggle button {
margin-right: 12px;
width: 28px;
height: 28px;
appearance: none;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.slider-footer .toggle button:hover {
background: rgba(255, 255, 255, 0.2);
}
.slider-footer p {
margin: 0;
color: #fff;
font-size: 18px;
margin-bottom: 10px;
}
.slider-indicator {
margin: 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
}
.slider-indicator li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background: #fff;
opacity: 0.4;
cursor: pointer;
}
.slider-indicator li.active {
width: 12px;
height: 12px;
opacity: 1;
}
</style>
</head>
<body>
<div class="slider">
<div class="slider-wrapper">
<img src="./slider01.jpg" alt="" />
</div>
<div class="slider-footer">
<p>对人类来说会不会太超前了?</p>
<ul class="slider-indicator">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="toggle">
<button class="prev"><</button>
<button class="next">></button>
</div>
</div>
</div>
<script>
// 1. 初始数据
const sliderData = [
{ url: './slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },
{ url: './slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },
{ url: './slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },
{ url: './slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },
{ url: './slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },
{ url: './slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },
{ url: './slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },
{ url: './slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },
]
let i = 0
let time = 0
const p = document.querySelector('.slider-footer p')
const img = document.querySelector('.slider-wrapper img')
// 左侧按钮点击,变量--,如果小于0,则复原最后一张
const prev = document.querySelector('.toggle .prev')
prev.addEventListener('click', function () {
i--
if (i < 0) {
i = 7
}
// 更改图片,文字信息
img.src = sliderData[i].url
p.innerHTML = sliderData[i].title
// 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
const activeClass = document.querySelector('.slider-indicator .active').classList.remove('active')
const active = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
})
//右侧按钮点击,变量++,如果大于等于8,则复原0
const next = document.querySelector('.toggle .next')
next.addEventListener('click', function () {
i++
if (i >= sliderData.length) {
i = 0
}
// 更改图片,文字信息
img.src = sliderData[i].url
p.innerHTML = sliderData[i].title
// 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
const activeClass = document.querySelector(' .slider-indicator .active').classList.remove('active')
const active = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
})
// 鼠标经过暂停定时
const slider = document.querySelector('.slider')
slider.addEventListener('mouseenter', function () {
clearInterval(time)
})
// 鼠标离开开启定时
slider.addEventListener('mouseleave', function () {
time = setInterval(function () {
i++
//无缝衔接位置
if (i >= sliderData.length) {
i = 0
}
// 更改图片,文字信息
img.src = sliderData[i].url
p.innerHTML = sliderData[i].title
// 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
const activeClass = document.querySelector(' .slider-indicator .active').classList.remove('active')
const active = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
}, 1000)
})
</script>
</body>
</html>
焦点事件:小米搜索框
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
.mi {
position: relative;
width: 223px;
margin: 100px auto;
}
.mi input {
width: 223px;
height: 48px;
padding: 0 10px;
font-size: 14px;
line-height: 48px;
border: 1px solid #e0e0e0;
outline: none;
}
.mi .search {
border: 1px solid #ff6700;
}
.result-list {
display: none;
position: absolute;
left: 0;
top: 48px;
width: 223px;
border: 1px solid #ff6700;
border-top: 0;
background: #fff;
}
.result-list a {
display: block;
padding: 6px 15px;
font-size: 12px;
color: #424242;
text-decoration: none;
}
.result-list a:hover {
background-color: #eee;
}
</style>
</head>
<body>
<div class="mi">
<input type="search" placeholder="小米笔记本">
<ul class="result-list">
<li><a href="#">全部商品</a></li>
<li><a href="#">小米11</a></li>
<li><a href="#">小米10S</a></li>
<li><a href="#">小米笔记本</a></li>
<li><a href="#">小米手机</a></li>
<li><a href="#">黑鲨4</a></li>
<li><a href="#">空调</a></li>
</ul>
</div>
<script>
//'[type=search]'是属性选择器
const input = document.querySelector('[type=search]')
const ul = document.querySelector('.result-list')
//获得焦点
input.addEventListener('focus',function(){
ul.style.display = 'block'
input.classList.add('search')
})
//失去焦点
input.addEventListener('blur',function(){
ul.style.display = 'none'
input.classList.remove('search')
})
</script>
</body>
</html>
键盘事件:评论字数统计
分析:
- 判断用户输入事件input
- 不断取得文本框里面的字符长度,文本域.value.length
- 把获得数字给下面文本框
<!DOCTYPE html>
<html lang="en">
<head>
<title>评论回车发布</title>
<style>
.wrapper {
min-width: 400px;
max-width: 800px;
display: flex;
justify-content: flex-end;
}
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
overflow: hidden;
background: url(./images/avatar.jpg) no-repeat center / cover;
margin-right: 20px;
}
.wrapper textarea {
outline: none;
border-color: transparent;
resize: none;
background: #f5f5f5;
border-radius: 4px;
flex: 1;
padding: 10px;
transition: all 0.5s;
height: 30px;
}
.wrapper textarea:focus {
border-color: #e4e4e4;
background: #fff;
height: 50px;
}
.wrapper button {
background: #00aeec;
color: #fff;
border: none;
border-radius: 4px;
margin-left: 10px;
width: 70px;
cursor: pointer;
}
.wrapper .total {
margin-right: 80px;
color: #999;
margin-top: 5px;
opacity: 0;
transition: all 0.5s;
}
.list {
min-width: 400px;
max-width: 800px;
display: flex;
}
.list .item {
width: 100%;
display: flex;
}
.list .item .info {
flex: 1;
border-bottom: 1px dashed #e4e4e4;
padding-bottom: 10px;
}
.list .item p {
margin: 0;
}
.list .item .name {
color: #FB7299;
font-size: 14px;
font-weight: bold;
}
.list .item .text {
color: #333;
padding: 10px 0;
}
.list .item .time {
color: #999;
font-size: 12px;
}
</style>
</head>
<body>
<div class="wrapper">
<i class="avatar"></i>
<textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
<button>发布</button>
</div>
<div class="wrapper">
<span class="total">0/200字</span>
</div>
<div class="list">
<div class="item" style="display: none;">
<i class="avatar"></i>
<div class="info">
<p class="name">清风徐来</p>
<p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
<p class="time">2022-10-10 20:29:21</p>
</div>
</div>
</div>
<script>
const tx = document.querySelector('#tx')
const total = document.querySelector('.total')
//当我们的文本获得焦点,就让total显示出来
tx.addEventListener('focus',function(){
total.style.opacity = 1
})
//当我们的文本失去焦点,就让total隐藏
tx.addEventListener('blur',function(){
total.style.opacity = 0
})
//检测用户输入
tx.addEventListener('input',function(){
total.innerHTML = `${tx.value.length}/100`
})
</script>
</body>
4.2事件对象
目标:能说出什么是事件对象
事件对象是什么:
也是个对象,这个对象里有事件触发时的关键信息
例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
使用场景:
可以判断用户按下哪个键,比如按下回车可以发布新闻
可以判断鼠标点击了哪个元素,从而做出响应的操作
语法:如何获取
在事件绑定的回调函数的第一个参数就是事件对象
一般命名为event,ev,e
元素.addEventListener('click',fuction (e) {
})
事件对象常用属性:
type | 获取当前的事件类型 |
clientX / clientY | 获取光标相对于浏览器可见窗口左上角的位置 |
offsetX / offsetY | 获取光标相对于当前DOM元素左上角的位置 |
key | 用户按下的键盘的值 现在不提倡使用keyCode |
案例:按下回车键
<body>
<input type="text">
<script>
const input = document.querySelector('input')
input.addEventListener('keyup',function(e){
if(e.key === 'Enter'){
console.log('我按下了回车键')
}
})
</script>
</body
案例:评论回车发布
需求:按下回车键,可以发布信息
分析:
用到按下键盘事件keydown或者keyup都可以
如果用户按下的是回车键,则发布信息
让留言信息模块显示,把拿到的数据渲染到对应标签nei
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.wrapper {
min-width: 400px;
max-width: 800px;
display: flex;
justify-content: flex-end;
}
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
overflow: hidden;
background: url(./images/avatar.jpg) no-repeat center / cover;
margin-right: 20px;
}
.wrapper textarea {
outline: none;
border-color: transparent;
resize: none;
background: #f5f5f5;
border-radius: 4px;
flex: 1;
padding: 10px;
transition: all 0.5s;
height: 30px;
}
.wrapper textarea:focus {
border-color: #e4e4e4;
background: #fff;
height: 50px;
}
.wrapper button {
background: #00aeec;
color: #fff;
border: none;
border-radius: 4px;
margin-left: 10px;
width: 70px;
cursor: pointer;
}
.wrapper .total {
margin-right: 80px;
color: #999;
margin-top: 5px;
opacity: 0;
transition: all 0.5s;
}
.list {
min-width: 400px;
max-width: 800px;
display: flex;
}
.list .item {
width: 100%;
display: flex;
}
.list .item .info {
flex: 1;
border-bottom: 1px dashed #e4e4e4;
padding-bottom: 10px;
}
.list .item p {
margin: 0;
}
.list .item .name {
color: #FB7299;
font-size: 14px;
font-weight: bold;
}
.list .item .text {
color: #333;
padding: 10px 0;
}
.list .item .time {
color: #999;
font-size: 12px;
}
</style>
</head>
<body>
<div class="wrapper">
<i class="avatar"></i>
<textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
<button>发布</button>
</div>
<div class="wrapper">
<span class="total">0/200字</span>
</div>
<div class="list">
<div class="item" style="display: none;">
<i class="avatar"></i>
<div class="info">
<p class="name">清风徐来</p>
<p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
<p class="time">2022-10-10 20:29:21</p>
</div>
</div>
</div>
<script>
const tx = document.querySelector('#tx')
const total = document.querySelector('.total')
const item = document.querySelector('.item')
const text = document.querySelector('.text')
tx.addEventListener('focus', function () {
total.style.opacity = 1
})
tx.addEventListener('blur', function () {
total.style.opacity = 0
})
tx.addEventListener('input', function () {
total.innerHTML = `${tx.value.length}/100`
})
tx.addEventListener('keyup', function (e) {
if (e.key === 'Enter') {
//如果用户输入的不为空就显示和打印
if (tx.value.trim()) {
item.style.display = 'block'
//用户输入的内容
text.innerHTML = tx.value
}
//按下回车清空文本域
tx.value = ''
total.innerHTML = '0/200字'
}
})
</script>
</body>
</html>
4.3环境对象
目标:能够分析判断函数运行在不同环境中this所指代的对象
环境对象:指的是函数内部特殊的变量this,它代表着当前函数运行时所处的环境
作用:弄清楚this的指向,可以让我们代码更简洁
- 函数的调用方式不同,this指代的对象也不同
- 【谁调用,this就是谁】是判断this指向的粗略规则
- 直接调用函数,其实相当于是window函数,所以this指代window
<body>
<button>点击</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click',function(){
console.log(this) //btn对象
this.style.color = 'red'
})
</script>
</body>
4.4回调函数
目标:能够说出什么是回调函数
如果将函数A作为参数传递给函数B时,我们称函数A为回调函数
简单理解:当一个函数当作参数来传递给另外一个函数的时候,这个函数就是回调函数
<body>
<button>点击</button>
<script>
function fn() {
console.log('我是回调函数')
}
//fn传递给了setInterval,fn就是回调函数
setInterval(fn, 1000)
</script>
</body>
案例:tab栏切换
<!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>tab栏切换</title>
<style>
* {
margin: 0;
padding: 0;
}
.tab {
width: 590px;
height: 340px;
margin: 20px;
border: 1px solid #e4e4e4;
}
.tab-nav {
width: 100%;
height: 60px;
line-height: 60px;
display: flex;
justify-content: space-between;
}
.tab-nav h3 {
font-size: 24px;
font-weight: normal;
margin-left: 20px;
}
.tab-nav ul {
list-style: none;
display: flex;
justify-content: flex-end;
}
.tab-nav ul li {
margin: 0 20px;
font-size: 14px;
}
.tab-nav ul li a {
text-decoration: none;
border-bottom: 2px solid transparent;
color: #333;
}
.tab-nav ul li a.active {
border-color: #e1251b;
color: #e1251b;
}
.tab-content {
padding: 0 16px;
}
.tab-content .item {
display: none;
}
.tab-content .item.active {
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<li><a class="active" href="javascript:;">精选</a></li>
<li><a href="javascript:;">美食</a></li>
<li><a href="javascript:;">百货</a></li>
<li><a href="javascript:;">个护</a></li>
<li><a href="javascript:;">预告</a></li>
</ul>
</div>
<div class="tab-content">
<div class="item active"><img src="./tab00.png" alt="" /></div>
<div class="item"><img src="./tab01.png" alt="" /></div>
<div class="item"><img src="./tab02.png" alt="" /></div>
<div class="item"><img src="./tab03.png" alt="" /></div>
<div class="item"><img src="./tab04.png" alt="" /></div>
</div>
</div>
<script>
const a = document.querySelectorAll('.tab-nav a')
//遍历每一个
for (let i = 0; i < a.length; i++) {
//添加鼠标经过事件
a[i].addEventListener('mouseenter', function () {
//排它思想,先移除后添加
document.querySelector('.tab-nav .active').classList.remove('active')
// a[i].classList.add('active')
this.classList.add('active')
//下面五个大盒子一一对应 .item
//排它思想
document.querySelector('.tab-content .active').classList.remove('active')
document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
</body>
</html>
全选文本框案例1 :
需求:用户点击全选,则下面复选框全部选择,取消全选则全部取消
分析:
- 全选复选框点击,可以得到当前按钮的 checked
- 把下面所有的小复选框状态checked,改为和全选复选框一致
- 遍历下面的所有的checked,添加点击事件
- 检查小复选框选中的个数,是不是等于小复选框总的个数
- 把结果给 全选按钮
- 利用css 复选框选择器 input:checked
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 500px;
margin: 100px auto;
text-align: center;
}
th {
background-color: #09c;
font: bold 16px "微软雅黑";
color: #fff;
height: 24px;
}
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.allCheck {
width: 80px;
}
</style>
</head>
<body>
<table>
<tr>
<th class="allCheck">
<input type="checkbox" name="" id="checkAll"> <span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
//获取大复选框
const checkAll = document.querySelector('#checkAll')
//获取所有的小复选框
const cks = document.querySelectorAll('.ck')
//点击大复选框,注册事件
checkAll.addEventListener('click', function () {
//得到当前大复选框的选中状态
//console.log(checkAll.checked) //是false 或者 true
//遍历所有的小复选框,让小复选框的checked = 大复选框的checked
for (let i = 0; i < cks.length; i++) {
cks[i].checked = checkAll.checked
}
})
//小复选框控制大复选框
for (let i = 0; i < cks.length; i++) {
cks[i].addEventListener('click',function(){
//判断选中的小复选框的个数 是不是等于 总的小复选框个数
//一定要写到点击里面,因为每次要获得最新的个数
console.log(document.querySelectorAll('.ck:checked').length) //小复选框被选中的个数
console.log(document.querySelectorAll('.ck:checked').length === cks.length) //选中的小复选框个数是否等于总复选框个数,返回的是true或者false
checkAll.checked = document.querySelectorAll('.ck:checked').length === cks.length
})
}
</script>
</body>
</html>
5.事件流
5.1事件流和两个阶段说明
事件流指的是事件完整执行过程中的流动路径
- 说明:假设页面里面有个div,当触发事件时,会经历两个阶段,分别是捕获阶段,冒泡阶段
- 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
- 实际工作都是使用事件冒泡为主
5.2事件捕获
事件捕获概念:
- 从DOM的根元素开始去执行对应的事件(从外到里)
- 事件捕获需要写对应代码才能看到效果
代码:
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
说明:
addEventListener第三个参数传入true代表的是捕获阶段触发(很少使用)
若传入false代表冒泡阶段触发,默认就是false
若是用L0事件监听,则只有冒泡阶段,没有捕获
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.father{
width: 200px;
height: 200px;
background-color:palegoldenrod;
}
.son{
width: 100px;
height: 100px;
background-color:plum;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
const fa = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
}, true)
fa.addEventListener('click', function () {
alert('我是爸爸')
}, true)
son.addEventListener('click', function () {
alert('我是儿子')
}, true)
</script>
</body>
</html>
5.3事件冒泡
事件冒泡概念:
一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
- 事件冒泡是默认存在的
- L2事件监听第三个参数是false,或者默认都是冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.father{
width: 200px;
height: 200px;
background-color:palegoldenrod;
}
.son{
width: 100px;
height: 100px;
background-color:plum;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
const fa = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
})
fa.addEventListener('click', function () {
alert('我是爸爸')
})
son.addEventListener('click', function () {
alert('我是儿子')
})
</script>
</body>
</html>
5.4阻止冒泡
问题:因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
需求:若想把事件就限制在当前元素内,就需要阻止事件冒泡
前提:阻止事件冒泡需要拿到事件对象
语法:
事件对象.stopPropagation()
注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.father{
width: 200px;
height: 200px;
background-color:palegoldenrod;
}
.son{
width: 100px;
height: 100px;
background-color:plum;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
const fa = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
})
fa.addEventListener('click', function () {
alert('我是爸爸')
})
son.addEventListener('click', function (e) {
alert('我是儿子')
//阻止流动传播
e.stopPropagation()
})
</script>
</body>
</html>
5.5阻止默认行为
我们某些情况下需要阻止默认行为的发生,比如 阻止 链接的跳转,表单域跳转
语法:
e.preventDefault( )
案例:
<body>
<form action="http://www.itcast.cn">
<input type="submit" value="免费注册">
</form>
<a href="http://www.baidu.com"></a>
<script>
const form = document.querySelector('form')
form.addEventListener('submit', function (e) {
//阻止默认行为 提交
//在某些情况下没有满足提交条件时需要阻止默认行为
e.preventDefault()
})
const a = document.querySelector('a')
a.addEventListener('click', function (e) {
e.preventDefault()
})
</script>
</body>
5.6事件解绑
on事件方式,直接使用null覆盖就可以实现事件解绑
//绑定事件
btn.onclick = function() {
alert('点击了')
}
//解绑事件
btn.onclick = null
addEventListener方式,必须使用:
removeEventListener(事件类型,事件处理函数,【获取捕获或者冒泡阶段】)
注意:匿名函数无法被解绑
function fn() {
alert('点击了')
}
//绑定事件
btn.addEventListener('click',fn)
//解绑事件
btn.removeEventListener('click',fn)
5.7鼠标经过事件的区别:
鼠标经过事件:
- mouseover和mouseout会有冒泡效果
- mouseenter和mouseleave没有冒泡效果(推荐)
传统on注册(L0):
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖就可以实现事件解绑
- 都是冒泡阶段执行的
事件监听注册(L2):
- 语法:addEventListener(事件类型,事件处理函数,是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡阶段或者捕获阶段执行
- 必须使用removeEventListener(事件类型,事件处理函数,获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
6.事件委托
事件委托是利用事件流的特征解决一些开发需求的知识技巧
优点:减少注册次数,可以提高程序性能
原理:事件委托其实是利用事件冒泡的特点
给父元素注册事件,当我们触发子元素的时候,就会冒泡到父元素身上,从而触发父元素的事件
实现:事件对象.target.tagName可以获得真正触发事件的元素
<body>
<ul>
<li>我是第1个li标签</li>
<li>我是第2个li标签</li>
<li>我是第3个li标签</li>
<li>我是第4个li标签</li>
<li>我是第5个li标签</li>
<p>这是p标签</p>
</ul>
<script>
//点击每一个小li 当前li 文字变为红色
//按照事件委托的方式 委托给父级 事件写到父级上
//1.获得父元素
const ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
//console.log(e.target) 点击的那个对象
//我们的需求,只需要点击li才会有效果
if (e.target.tagName === 'LI') {
e.target.style.color = 'red'
}
})
</script>
</body>
案例:tab栏切换-事件委托版
//css样式不变
<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="./tab00.png" alt="" /></div>
<div class="item"><img src="./tab01.png" alt="" /></div>
<div class="item"><img src="./tab02.png" alt="" /></div>
<div class="item"><img src="./tab03.png" alt="" /></div>
<div class="item"><img src="./tab04.png" alt="" /></div>
</div>
</div>
<script>
//使用事件委托
//1.获得父元素
const ul = document.querySelector('ul')
//2.添加点击事件
ul.addEventListener('click', function (e) {
//e.target是我们点击的对象
console.log(e.target)
//只有当点击a标签时才会生效
if (e.target.tagName === 'A') {
//排它思想 先移除原来的active
document.querySelector('.tab-nav .active').classList.remove('active')
//this指向ul 不能用this
e.target.classList.add('active')
//大盒子模块
//因为data-id="0"采用的是字符串类型,需要转换为数字类型
const i = +e.target.dataset.id
document.querySelector('.tab-content .active').classList.remove('active')
document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
}
})
</script>
</body>
知识点补充—css自定义属性:
<body>
<div data-id="0"></div>
<script>
const div = document.querySelector('div')
console.log(div.dataset.id) //0
</script>
</body>
7.其他事件
7.1页面加载事件
Load事件:
加载外部资源(如图片,外联css和javscript等)加载完毕时触发的事件
为什么要学?
- 有些时候需要等待页面资源全部处理完了做一些事情
- 老代码喜欢把script写在head中,这时候直接找dom元素找不到
事件名:load
监听页面所有资源加载完毕:
给window添加load事件
<head>
<script>
//等待页面所有资源加载完毕,就回去执行回调函数
window.addEventListener('load',function(){
const btn = document.querySelector('button')
btn.addEventListener('click',function(){
alert(11)
})
})
img.addEventListener('load',function(){
//等待图片加载完毕,再去执行里面的代码
})
</script>
</head>
<body>
<button>点击</button>
</body>
</html>
注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
DOMContentLoaded事件:
当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表,图像等完全加载
事件名:DOMContentLoaded
事件页面DOM加载完毕:
- 给document添加DOMContentLoaded事件
document.addEventListener('DOMContentLoaded',function(){
const btn = document.querySelector('button')
btn.addEventListener('click',function(){
alert(11)
})
})
页面加载事件有哪两个?如何添加?
load事件:监听整个页面资源给Window加
DOMContentLoaded事件:给document加,无需等待样式表,图像等完全加载
7.2元素滚动事件
滚动条在滚动的时候持续触发的事件
为什么要学?
很多页面需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部
事件名:scroll
监听整个页面滚动:
//页面滚动事件
window.addEventListener('scroll',function(){
//执行的操作
})
- 给window或document添加scroll事件
- 监听某个元素的内部滚动直接给某个元素添加即可
获取位置-scrollLeft和scrollTop(属性):
- 获取被卷去的大小
- 获取元素内容往左,往上滚出去看不到的距离
- 这两个值是可读写的
<head>
<style>
body {
padding-top: 100px;
height: 3000px;
}
div {
margin: 100px;
overflow: scroll;
width: 200px;
height: 200px;
border: 1px solid #000
}
</style>
</head>
<body>
<div>
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
</div>
<script>
const div = document.querySelector('div')
div.addEventListener('scroll', function () {
//通过div.scrollTop知道div内滚动了多少
console.log(div.scrollTop)
//获取html元素写法,通过document.documentElement.scrollTop知道页面到底滚动了多少
console.log(document.documentElement.scrollTop)
})
</script>
</body>
</html>
在HTML页面中滚动100px后出现div,往回滚动小于100px时div消失:
<head>
<style>
body {
padding-top: 100px;
height: 3000px;
}
div {
display: none;
margin: 100px;
overflow: scroll;
width: 200px;
height: 200px;
border: 1px solid #000
}
</style>
</head>
<body>
<div>
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
我里面有很多文字
</div>
<script>
const div = document.querySelector('div')
window.addEventListener('scroll', function () {
//当HTML页面滚动了100px时出现div
const n = document.documentElement.scrollTop
if (n >= 100) {
div.style.display = 'block'
} else {
div.style.display = 'none'
}
})
</script>
</body>
滚动到指定的坐标-scrollTo()
scrollTo()方法可把内容滚动到指定的坐标
语法:
元素.scrollTo(x,y)
//让页面滚动到y轴1000像素的位置
window.scrollTo(0,1000)
电梯导航案例:
<!-- 电梯 -->
<div class="xtx-elevator">
<ul class="xtx-elevator-list">
<li><a href="javascript:;" data-name="new">新鲜好物</a></li>
<li><a href="javascript:;" data-name="popular">人气推荐</a></li>
<li><a href="javascript:;" data-name="brand">热门品牌</a></li>
<li><a href="javascript:;" data-name="topic">最新专题</a></li>
<li><a href="javascript:;" id="backTop"><i class="sprites"></i>顶部</a></li>
</ul>
</div>
<script>
const elevator = document.querySelector('.xtx-elevator')
window.addEventListener('scroll', function () {
const n = document.documentElement.scrollTop
// if (n >= 300) {
// elevator.style.opacity = 1
// } else {
// elevator.style.opacity = 0
// }
elevator.style.opacity = n >= 300 ? 1 : 0
})
//点击返回页面顶部
const backTop = document.querySelector('#backTop')
backTop.addEventListener('click',function(){
//可读写
// document.querySelectorAll.scrollTop = 0
// window.scrollTo(x,y)
window.scrollTo(0,0)
})
</script>
7.3页面尺寸事件
获取元素宽高:
- 获取元素的可见部分宽高(不包含边框,margin,滚动条等)
- clientWidth和clientHeight
会在窗口尺寸改变的时候触发事件:
- resize
window.addEventListener('resize',function(){})
检测屏幕宽度:
window.addEventListener('resize',function(){
let w = document.documentElement.clientWidth
console.log(w)
})
元素尺寸于位置:
使用场景:
- 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事
- 简单说,就是通过js的方式,得到元素在页面中的位置
- 这样我们可以做,页面滚动到这个位置,就可以做某些操作,省去计算了
元素尺寸于位置-尺寸
获取宽高:
-
获取元素的自身高度,包括元素自身设置的宽高,padding,border
-
offsetWidth和offsetHeight
-
获取出来的是数值,方便计算
-
注意:获取的是可视宽高,如果盒子是隐藏的,获取到的结果是0
获取位置:
-
获取元素距离自己定位父级元素的左,上距离
-
offsetLeft和offsetTop注意是只读属性
<!DOCTYPE html>
<html lang="en">
<head>
<style>
div {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
margin: 100px;
}
p{
width: 100px;
height: 100px;
background-color: purple;
margin: 50px;
}
</style>
</head>
<body>
<div>
<p></p>
</div>
<script>
const div = document.querySelector('div')
const p = document.querySelector('p')
//检测盒子的位置 最近一级带有定位的祖先元素
console.log(p.offsetLeft)
</script>
</body>
</html>
offsetWidth和offsetHeight是得到元素什么高度?
- 内容+padding+border
offsetTop和offsetLeft得到的位置以谁为准?
- 带有定位的父级
- 如果都没用则以文档左上角
仿东京固定导航栏案例
需求:当页面滚动到秒杀模块,导航栏自动滑入,否则滑出
分析:
- 用到页面滚动事件
- 检测页面滚动大于等于秒杀模块的位置则滑入,否则滑出
- 主要移动的是秒杀模块的顶部位置
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content {
overflow: hidden;
width: 1000px;
height: 3000px;
background-color: pink;
margin: 0 auto;
}
.backtop {
display: none;
width: 50px;
left: 50%;
margin: 0 0 0 505px;
position: fixed;
bottom: 60px;
z-index: 100;
}
.backtop a {
height: 50px;
width: 50px;
background: url(./images/bg2.png) 0 -600px no-repeat;
opacity: 0.35;
overflow: hidden;
display: block;
text-indent: -999em;
cursor: pointer;
}
.header {
position: fixed;
top: -80px;
left: 0;
width: 100%;
height: 80px;
background-color: purple;
text-align: center;
color: #fff;
line-height: 80px;
font-size: 30px;
transition: all .3s;
}
.sk {
width: 300px;
height: 300px;
background-color: skyblue;
margin-top: 500px;
}
</style>
</head>
<body>
<div class="header">我是顶部导航栏</div>
<div class="content">
<div class="sk">秒杀模块</div>
</div>
<div class="backtop">
<img src="./images/close2.png" alt="">
<a href="javascript:;"></a>
</div>
<script>
const sk = document.querySelector('.sk')
const header = document.querySelector('.header')
window.addEventListener('scroll', function () {
//当页面滚动到 秒杀模块的时候,就改变头部的top值
//页面被卷去的头部 >= 秒杀模块的位置 offsetTop
const n = document.documentElement.scrollTop
// if (n >= sk.offsetTop) {
// header.style.top = 0
// }else{
// header.style.top = '-80px'
// }
header.style.top = n >= sk.offsetTop ? 0 : '-80px'
})
</script>
</body>
</html>
实现bilibili点击小滑块移动效果
需求:当点击链接,下面红色滑块跟着移动
分析:
- 用到事件委托
- 点击链接得到当前元素的offsetLeft值
- 修改line颜色块的transform值 = 点击链接的offsetLeft
- 添加过渡效果
<script>
const list = document.querySelector('.tabs-list')
const line = document.querySelector('.line')
list.addEventListener('click', function (e) {
if (e.target.tarName = 'A') {
// console.log(11)
// console.log((e.target.offsetLeft - 16) / 3.75 + 'vw')
// console.log((e.target.offsetLeft) / 3.75 + 'vw')
line.style.left = (e.target.offsetLeft + 16) / 3.75 + 'vw'
}
})
</script>
元素尺寸于位置-尺寸 获取位置:
element.getBoundingClientRect()
方法返回元素的大小及其相对于视口的位置
总结:
8.日期对象
8.1实例化
目标:能够实例化日期对象
- 在代码中发现了neW关键字时,一般将这个操作称为实例化
- 创建一个时间对象并获取时间
获得当前时间:
const date = new Date()
获得指定时间:
const date = new Date('2008-8-8')
console.log(date)
8.2时间对象方法
目标:能够使用日期对象中的方法写出常见日期
使用场景:因为日期对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式
//获得日期对象
const date = new Date()
//使用里面的方法
console.log(date.getFullYear())
console.log(date.getMonth()+1) //需要+1
console.log(date.getDate())
console.log(date.getDay())/星期几
案例-页面显示时间
需求:将当前时间以:YYYY-MM-DD HH:mm形式显示在页面2008-08-08 08:08
分析:
①:调用日期对象方法进行转换
②:记得数字要补0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div></div>
<script>
const div = document.querySelector('div')
function getMyDate() {
const date = new Date()
//判断是否大于10
let h = date.getHours()
let m = date.getMinutes()
let s = date.getSeconds()
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
return `今天是${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日
${h}:${m}:${s}`
}
//解决页面刚刷新的空白问题
div.innerHTML = getMyDate()
//定时器,页面的时间戳可以随之变化
setInterval(function () {
//div中的文字返回的是getMyDate()的结果
div.innerHTML = getMyDate()
}, 1000)
</script>
</body>
</html>
另一种写法:
<body>
<div></div>
<script>
const div = document.querySelector('div')
const date = new Date()
div.innerHTML = date.toLocaleString()
</script>
</body>
</html>
2023/10/4 17:46:49
8.3时间戳
目标:能够获得当前时间戳
使用场景:如果计算倒计时效果,前面方法无法直接计算,需要借助于时间戳完成(因为年月日无法直接相加减,所以使用时间戳)
什么是时间戳:
- 是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
算法:
- 将来的时间戳-现在的时间戳=剩余时间毫秒数
- 剩余时间毫秒数 转换为 剩余时间的年月日时分秒就是倒计时时间
- 比如,将来时间戳2000ms-现在时间戳1000ms=1000ms
- 1000m5转换为就是0小时0分1秒
三种方式获取时间戳:
1.使用getTime()方法——必须需实例化
const date = new Date()
console.log(date.getTime())
2.简写+new Date()——无需实例化
console.log(+new Date())
3.使用Date.now()——无需实例化
但是只能得到当前的时间戳,而前面两种可以返回指定的时间戳
console.log(Date.now())
获取指定时间戳:
console.log(+new Date('2023-4-1 23:10:00'))
根据日期Day() 0~6 返回的是星期一:
<script>
//根据日期Day() 0~6 返回的是星期一
const arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
console.log(arr[new Date().getDay()])
</script>
9.节点操作
9.1DOM节点
目标:能说出DOM节点的类型
DOM节点:
DOM树里每一个内容都称之为节点
节点类型:
元素节点
- 所有的标签比如body、div
- html是根节点
属性节点
- 所有的属性比如href
文本节点
- 所有的文本
其他
9.2查找节点
目标:能够具备根据节点关系查找目标节点的能力
关闭二维码案例:
点击关闭按钮,关闭的是二维码的盒子,还要获取erweima盒子
思考:
- 关闭按钮和erweima是什么关系呢?
- 父子关系
- 所以,我们完全可以这样做:
- 点击关闭按钮,直接关闭它的爸爸,就无需获取erweima元素了
节点关系:针对的找亲戚返回的都是对象
- 父节点
- 子节点
- 兄弟节点
父节点查找:
parentNode属性
返回最近一级的父节点 找不到返回null
<body>
<div class="grandfeather">
<div class="feather">
<div class="baby"></div>
</div>
</div>
<script>
const baby = document.querySelector('.baby')
//子节点
console.log(baby)
//父节点
console.log(baby.parentNode)
//父节点的父节点
console.log(baby.parentNode.parentNode)
</script>
</body>
点击关闭广告案例:
<head>
<style>
.box {
position: relative;
width: 1000px;
height: 200px;
background-color: pink;
margin: 100px auto;
text-align: center;
font-size: 50px;
line-height: 200px;
font-weight: 700;
}
.box1 {
position: absolute;
right: 20px;
top: 10px;
width: 20px;
height: 20px;
background-color: skyblue;
text-align: center;
line-height: 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
我是广告
<div class="box1">X</div>
</div>
<script>
// 1. 获取事件源
const box1 = document.querySelector('.box1')
// 2. 事件侦听
box1.addEventListener('click', function () {
this.parentNode.style.display = 'none'
})
</script>
</body>
多个广告窗口-点击哪个关闭哪个:
<body>
<div class="box">
我是广告
<div class="box1">X</div>
</div>
<div class="box">
我是广告
<div class="box1">X</div>
</div>
<div class="box">
我是广告
<div class="box1">X</div>
</div>
<script>
//注册事件,多个关闭按钮,点击谁谁关闭
const closeBtn = document.querySelectorAll('.box1')
for (let i = 0; i < closeBtn.length; i++) {
closeBtn[i].addEventListener('click', function () {
this.parentNode.style.display = 'none'
})
}
</script>
</body>
子节点查找:
childNodes
- 获得所有子节点、包括文本节点(空格、换行)、注释节点等
children属性(重点)
- 仅获得所有元素节点
- 返回的还是一个伪数组
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
const ul = document.querySelector('ul')
console.log(ul.children) //得到伪数组 选择的是亲儿子
</script>
</body>
兄弟关系查找:
1.下一个兄弟节点
- nextElementSibling属性
2.上一个兄弟节点
- previousElementSibling属性
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
const li2 = document.querySelector('ul li:nth-child(2)')
console.log(li2.nextElementSibling) //下一个兄弟节点
console.log(li2.previousElementSibling)//上一个兄弟节点
</script>
</body>
9.3增加节点
目标:能够具备根据需求新增节点的能力
很多情况下,我们需要在页面中增加元素
- 比如,点击发布按钮,可以新增一条信息
一般情况下,我们新增节点,按照如下操作:
- 创建一个新的节点
- 把创建的新的节点放入到指定的元素内部
学习路线:
- 创建节点
- 追加节点
创建节点:
即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
创建元素节点方法:
//创建一个新的元素节点
document.createElement('标签名')
追加节点:
要想在界面看到,还得插入到某个父元素中
插入到父元素的最后一个子元素:
//插入到这个父元素的最后
父元素.appendChild(要插入的元素)
插入到父元素中某个子元素的前面:
//插入到某个子元素的前面
父元素.insertBefore(要插入的元素,在哪个元素前面)
案例:
<body>
<ul>
<li>我是老大</li>
</ul>
<script>
const ul = document.querySelector('ul')
//创建节点 li
const li = document.createElement('li')
li.innerHTML = '我是li'
//追加节点 作为最后一个元素
ul.appendChild(li)
//插入到父元素中某个子元素的前面
//创建节点 li
const li2 = document.createElement('li')
li2.innerHTML = '我是li2'
//ul.childern = ul中的子节点 >>> ul.childern[0] = ul中的第一个子节点
ul.insertBefore(li2, ul.children[0])
</script>
</body>
学成在线案例渲染:
需求:按照数据渲染页面
分析:
- 准备好空的ul结构
- 根据数据的个数,创建一个新的空li
- li里面添加内容img标题等
- 追加给ul
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>学车在线首页</title>
<link rel="stylesheet" href="./css/style.css">
<style>
</style>
</head>
<body>
<!-- 4. box核心内容区域开始 -->
<div class="box w">
<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>
<div class="box-bd">
<ul class="clearfix">
</ul>
</div>
</div>
<script>
// 1. 重构
let data = [
{
src: 'images/course01.png',
title: 'Think PHP 5.0 博客系统实战项目演练',
num: 1125
},
{
src: 'images/course02.png',
title: 'Android 网络动态图片加载实战',
num: 357
},
{
src: 'images/course03.png',
title: 'Angular2 大前端商城实战项目演练',
num: 22250
},
{
src: 'images/course04.png',
title: 'Android APP 实战项目演练',
num: 389
},
{
src: 'images/course05.png',
title: 'UGUI 源码深度分析案例',
num: 124
},
{
src: 'images/course06.png',
title: 'Kami2首页界面切换效果实战演练',
num: 432
},
{
src: 'images/course07.png',
title: 'UNITY 从入门到精通实战案例',
num: 888
},
{
src: 'images/course08.png',
title: 'Cocos 深度学习你不会错过的实战',
num: 590
},
]
const ul = document.querySelector('.box-bd ul')
// 1. 根据数据的个数,创建 对应的小li
for (let i = 0; i < data.length; i++) {
// 2. 创建新的小li
const li = document.createElement('li')
// 把内容给li
li.innerHTML = `
<a href="#">
<img src=${data[i].src} alt="">
<h4>
${data[i].title}
</h4>
<div class="info">
<span>高级</span> • <span>${data[i].num}</span>人在学习
</div>
</a>
`
// 3. ul追加小li
ul.appendChild(li)
}
</script>
</body>
</html>
克隆节点:
特殊情况下,我们新增节点,按照如下操作:
- 复制一个原有的节点
- 把复制的节点放入到指定的元素内部
//克隆一个已有的元素节点
元素.cloneNode(布尔值)
cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值:
- 若为true,则代表克隆时会包含后代节点一起克隆
- 若为false,则代表克隆时不包含后代节点
- 默认为false
<body>
<ul>
<li>我是老1</li>
<li>我是老2</li>
<li>我是老3</li>
<li>我是老4</li>
</ul>
<script>
const ul = document.querySelector('ul')
//1.克隆节点 元素.cloneNode(true)
const li1 = ul.children[0].cloneNode(true)
//2.追加
// ul.appendChild(li1)
ul.appendChild(ul.children[0].cloneNode(true)) //深拷贝
ul.appendChild(ul.children[0].cloneNode())//浅拷贝
</script>
</bo
9.4删除节点
目标:能够具备根据需求删除节点的能力
若一个节点在页面中已不需要时,可以删除它
在JavaScript原生DOM操作中,要删除元素必须通过父元素删除
语法:
父元素.removeChild(要删除的元素)
注:
- 如不存在父子关系则删除不成功
- 删除节点和隐藏节点(display:none)有区别的:隐藏节点还是存在的,但是删除,则从html中删除节点
<body>
<ul>
<li>我是老1</li>
<li>我是老2</li>
<li>我是老3</li>
<li>我是老4</li>
</ul>
<script>
const ul = document.querySelector('ul')
//删除节点 父元素.removeChlid(子元素)
ul.removeChild(ul.children[0])
</script>
</body>
10.M端事件
目标:了解M端常见的事件
移动端也有自己独特的地方。比如触屏事件touch(也称触摸事件),Android和IOS都有。
- 触屏事件touch(也称触摸事件),Android和IOS都有。
- touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔
- )对屏幕或者触控板操作。
常见的触屏事件如下:
触屏touch事件 | 说明 |
---|---|
touchstart | 手指触摸到一个DOM元素时触发 |
touchmove | 手指在一个DOM元素上滑动时触发 |
touchend | 手指从一个DOM元素上移开时触发 |
<!DOCTYPE html>
<html lang="en">
<head>
<style>
div {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
margin: 100px;
}
</style>
</head>
<body>
<div></div>
<script>
const div = document.querySelector('div')
//1.触摸
div.addEventListener('touchstart', function () {
console.log('开始摸我了')
})
//2.离开
div.addEventListener('touchend', function () {
console.log('离开了')
})
//3.移动
div.addEventListener('touchmove', function () {
console.log('一直摸,移动')
})
</script>
</body>
</html>
11.swiper插件--第124p
插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
学习插件的基本过程
熟悉官网,了解这个插件可以完成什么需求
https://www.swiper.com.cn/
看在线演示,找到符合自己需求的demo
https://www.swiper.com.cn/demo/index.html
查看基本使用流程
https://www.swiper.com.cn/usage/index.html
查看APi文档,去配置自己的插件 https://www.swiper.com.cn/api/index.html
注意:多个swiperl同时使用的时候,类名需要注意区分
12.Window对象
12.1BOM(浏览器对象模型)
- BOM(Browser Object Model)是浏览器对象模型
- window对象是一个全局对象,也可以说是JavaScript中的顶级对象
- 像document、alert()、console..log()这些都是window的属性,基本BOM的属性和方法都是window的。
- 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法
- window对象下的属性和方法调用的时候可以省略window
12.2定时器-延时函数
JavaScript内置的一个用来让代码延迟执行的函数,叫setTimeout
语法:
setTimeout(回调函数,等待的毫秒数)
setTimeout仅仅只执行一次,所以可以理解为就是把一段代码延迟执行,平时省略window
清除延时函数:
let timer=setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)
注意点:
延时器需要等待,所以后面的代码先执行
每一次调用延时器都会产生一个新的延时器
两种定时器对比:执行的次数
延时函数:执行一次
间歇函数:每隔一段时间就执行一次,除非手动清除
5秒钟之后消失的广告:
需求:5秒钟之后,广告自动消失
分析:
①:设置延时函数
②:隐藏元素
<head>
<style>
.box {
position: relative;
width: 1000px;
height: 200px;
background-color: pink;
margin: 100px auto;
text-align: center;
font-size: 50px;
line-height: 200px;
font-weight: 700;
}
.box1 {
position: absolute;
right: 20px;
top: 10px;
width: 20px;
height: 20px;
background-color: skyblue;
text-align: center;
line-height: 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
关闭广告
<div class="box1">X</div>
</div>
<script>
const div1 = document.querySelector('.box1')
setTimeout(function () {
div1.parentNode.style.display = 'none'
}, 5000)
</script>
</body>
12.3JS执行机制
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
- 这是因为Javascript这门脚本语言诞生的使命所致一JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
- 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
- JS执行机制
- 为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事
情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
他们的本质区别:这条流水线上各个流程的执行顺序不同。
同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
JS的异步是通过回调函数实现的。
一般而言,异步任务有以下三种类型:
1、普通事件,如click、resize等
2、资源加载,如load、error等
3、定时器,包括setinterval、setTimeout等
异步任务相关添加到任务队列中(任务队列也称为消息队列)。
- 1.先执行执行栈中的同步任务。
- 2.异步任务放入任务队列中。
- 3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
12.4location对象
location的数据类型是对象,它拆分并保存了URL地址的各个组成部分
常用属性和方法:
href属性获取完整的URL地址,对其赋值时用于地址的跳转
//可以得到当前文URL地址
console.log(location.href)
//可以通过js方式跳转到目标地址
location.href = 'http://www.itcast.cn'
search属性获取地址中携带的参数,符号?后面部分
console.log(location.search)
hash属性获取地址中的哈希值,符号#后面部分
后期Vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如网易云音乐
console.log(location.hash)
reload方法用来刷新当前页面,传入参数true时表示强制刷新
<body>
<button>点击刷新</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function () {
location.reload(true)
// 强制刷新类似ctrL+f5
})
</script>
</body>
5秒钟之后跳转的页面
需求:用户点击可以跳转,如果不点击,则5秒之后自动跳转,要求里面有秒数倒计时
分析:
①:目标元素是链接
②:利用定时器设置数字倒计时
③:时间到了,自动跳转到新的页面
<body>
<a href="http://www.baidu.com">支付将在<span>5</span>s后自动跳转</a>
<script>
const a = document.querySelector('a')
let num = 5
let timer = setInterval(function () {
num--
a.innerHTML = `支付将在${num}s后自动跳转`
if(num === 0){
clearInterval(timer)
location.href="http://www.baidu.com"
}
}, 1000)
</script>
</body>
12.5navigator对象
navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
常用属性和方法:
通过userAgent检测浏览器的版本及平台
![](https://i-blog.csdnimg.cn/blog_migrate/61f59601fee4d204788dc06f93a26c5e.png)
12.6histroy.对象
history的数据类型是对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
常用属性和方法:
history对象方法 | 作用 |
back() | 可以后退功能 |
formard() | 前进功能 |
go(参数) | 前进后退功能 参数如果是1 前进1个页面 如果是-1 后退1个页面 |
<body>
<button>前进</button>
<button>后退</button>
<script>
const back = document.querySelector('button:first-child')
const forward = back.nextElementSibling
back.addEventListener('click', function () {
history.go(-1)
})
forward.addEventListener('click', function () {
history.go(1)
})
</script>
</body>
13.本地存储
13.1本地存储介绍
以前我们页面写的数据一刷新页面就没有了,是不是?
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
1、数据存储在用户浏览器中
2、设置、读取方便、甚至页面刷新不丢失数据
3、容量较大,sessionStorage和localStorage约5M左右
常见的使用场景:
https://todomvc.com/examples/vanilla-es6/页面刷新数据不丢失
13.2本地存储分类-localStorage
目标:能够使用localStorage把数据存储的浏览器中
作用:可以将数据永久存储在本地(用户的电脑),除非手动删除,否则关闭页面也会存在
特性:
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储数据:
localStorage.setltem(key,value)
获取数据:
localStorage.getltem(key)
删除数据:
localStorage.removeltem(key)
<script>
//增
localStorage.setltem('uname', 'pink老师')
//查
console.log(localStorage.getltem('uname'))
//删
localStorage.removeltem('uname')
//改 如果原来有这个键,则是改,如果没有这个键,则是增
localStorage.setltem('uname', 'red老师')
//我要存一个年龄
//本地存储只能存储字符串数据类型
localStorage.setltem('age',18)
console.log(localStorage.getltem('age')) //打印出来是字符串类型
</script>
12.3本地存储分类-sessionStorage
特性:
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- 用法跟localStorage基本相同
13.4存储复杂数据类型
目标:能够存储复杂数据类型以及取出数据
本地只能存储字符串,无法存储复杂数据类型.
解决:需要将复杂数据类型转换成SON字符串,在存储到本地
语法:
JSON.stringify(复杂数据类型)
<script>
const obj = {
uname:'pink老师',
age:18,
gender:'女'
}
localStorage.setItem('obj',JSON.stringify(obj))
//JSON对象 属性和值有引号,而引号统一是双引号
//{"uname":"pink老师","age":18,"gender":"女"}
console.log(localStorage.getItem('obj')) //取出来是字符串
//把JSON字符串转换为 对象
console.log(JSON.parse(localStorage.getItem('obj'))) //取出来的是对象
</script>
14.数组map和join方法
数组中map方法 迭代数组
使用场景:
map可以遍历数组处理数据,并且返回新的数组
<script>
const arr = ['red','green','pink']
//map数组方法
const newArr = arr.map(function(ele,index){
console.log(ele)//数组元素
console.log(index)//索引号
return ele + '颜色'
})
console.log(newArr) //['red颜色', 'green颜色', 'pink颜色']
</script>
map也称为映射。映射是个术语,指两个元素的集之间元素相互"对应”的关系。
map重点在于有返回值,forEach没有返回值
数组中join方法
作用:
join()方法用于把数组中的所有元素转换一个字符串
语法:
//2.数组join方法 把数组转换为字符串
//小括号为空则逗号分割
console.log(newArr.join()) //red颜色,green颜色,pink颜色
//小括号是空字符串,则元素之间没有分隔符
console.log(newArr.join('')) //red颜色green颜色pink颜色
console.log(newArr.join('|')) //red颜色|green颜色|pink颜色
参数:
数组元素是通过参数里面指定的分隔符进行分隔的,空字符串( ' ' ),则所有元素之间都没有任何字符。
15.正则表达式
15.1介绍
什么是正则表达式:
正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象
通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。
请在上图中找出【戴帽子和眼镜的男人】
戴帽子、戴眼镜、男人都是描述信息,通过这些信息能够在人群中查找到确定的某个人,那么这些用于查找的描述信息编写一个模式,对应到计算机中就是所谓的正则表达式。
正则表达式在JavaScript中的使用场景:
例如验证表单:用户名表单只能输入英文字母、数字或者下划线,昵称输入框中可以输入中文(匹配)
比如用户名:/^[a-z0-9_-]{3,16}$/
过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等。
15.2语法
我们想要查找是否有戴眼镜的人,怎么做呢?
1.定义规则:戴眼镜的
2.根据规则去查找:找到则返回
正则同样道理,我们分为两步:
1.定义规则
2.查找
比如:查找下面文本中是否包含字符串'前端'
1et str='IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
JavaScript中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:
1.定义正则表达式语法:
//其中/ /是正则表达式字面量
const 变量名=/表达式/
比如:
const reg=/前端/
2.判断是否有符合规则的字符串:
//test()方法用来查看正则表达式与指定的字符串是否匹配
regobj.test(被检测的字符串)
比如:
<script>
//要检测的字符串
let str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
//1.定义正则表达式,检测规则
const reg = /前端/
//检测方法
console.log(reg.test(str)) //true
</script>
如果正则表达式与指定的字符串匹配,返回true,否则false
3.检索(查找)符合规则的字符串:
//exec()方法在一个指定字符串中执行一个搜索匹配
regObj.exec(被检测字符串)
比如:
<script>
//要检测的字符串
let str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
//1.定义正则表达式,检测规则
const reg = /前端/
//检测方法
console.log(reg.exec(str))
//['前端', index: 5, input: 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训', groups: undefined]
</script>
如果匹配成功,exec()方法返回一个数组,否则返回null
15.3元字符
目标:能说出什么是元字符以及它的好处
普通字符:
大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。
元字符(特殊字符):
是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
- 比如,规定用户只能输入英文26个英文字母,普通字符的话abcdefghijklm..
- 但是换成元字符写法:[a-z]
参考文档:
MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
正则测试工具:http://tool.oschina.net/regex
为了方便记忆和学习,我们对众多的元字符进行了分类:
- 边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
边界符号 | 说明 |
^ | 表示匹配行首的文本(以谁开始) |
$ | 表示匹配行尾的文本(以谁结束) |
如果^和$在一起,表示必须是精确匹配
// 元字符
console.log(/哈/.test('哈')) // true
console.log(/哈/.test('哈哈')) // true
console.log(/哈/.test('二哈')) // true
console.log('------------------')
// 1. 边界符
console.log(/^哈/.test('哈')) // true
console.log(/^哈/.test('哈哈')) // true
console.log(/^哈/.test('二哈')) // flase
console.log(/^哈$/.test('哈')) // true 只有这种情况为true 否则全是false
console.log(/^哈$/.test('哈哈')) // false
console.log(/^哈$/.test('二哈')) // false
- 量词(表示重复次数)
量词用来设定某个模式出现的次数
量词 | 说明 |
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
// // 量词 * 类似 >=0 次
//‘哈’ 能出现0次或无数次,但是不能出现除‘哈’以外的任何字
console.log(/^哈$/.test('哈')) // true
console.log(/^哈*$/.test('')) // true
console.log(/^哈*$/.test('哈')) // true
console.log(/^哈*$/.test('哈哈')) // true
console.log(/^哈*$/.test('二哈很傻')) // false
console.log(/^哈*$/.test('哈很傻')) // false
console.log(/^哈*$/.test('哈很哈')) // false
// console.log('------------------')
// // 量词 + 类似 >=1 次
console.log(/^哈$/.test('哈')) // true
console.log(/^哈+$/.test('')) // false
console.log(/^哈+$/.test('哈')) // true
console.log(/^哈+$/.test('哈哈')) // true
console.log(/^哈+$/.test('二哈很傻')) // false
console.log(/^哈+$/.test('哈很傻')) // false
console.log(/^哈+$/.test('哈很哈')) // false
// console.log('------------------')
// // 量词 ? 类似 0 || 1
console.log(/^哈?$/.test('')) // true
console.log(/^哈?$/.test('哈')) // true
console.log(/^哈?$/.test('哈哈')) // false
console.log(/^哈?$/.test('二哈很傻')) // false
console.log(/^哈?$/.test('哈很傻')) // false
console.log(/^哈?$/.test('哈很哈')) // false]
// 量词 {n} 写几,就必须出现几次
console.log(/^哈{4}$/.test('哈'))// false
console.log(/^哈{4}$/.test('哈哈'))// false
console.log(/^哈{4}$/.test('哈哈哈'))// false
console.log(/^哈{4}$/.test('哈哈哈哈'))// true
console.log(/^哈{4}$/.test('哈哈哈哈哈'))// false
console.log(/^哈{4}$/.test('哈哈哈哈哈哈'))// false
console.log('------------------')
// 量词 {n,} >=n
console.log(/^哈{4,}$/.test('哈'))// false
console.log(/^哈{4,}$/.test('哈哈'))// false
console.log(/^哈{4,}$/.test('哈哈哈'))// false
console.log(/^哈{4,}$/.test('哈哈哈哈'))// true
console.log(/^哈{4,}$/.test('哈哈哈哈哈'))// true
console.log(/^哈{4,}$/.test('哈哈哈哈哈哈'))// true
console.log('------------------')
// 量词 {n,m} 逗号左右两侧千万不能有空格 >=n && <= m
console.log(/^哈{4,6}$/.test('哈'))// false
console.log(/^哈{4,6}$/.test('哈哈'))// false
console.log(/^哈{4,6}$/.test('哈哈哈'))// false
console.log(/^哈{4,6}$/.test('哈哈哈哈'))// true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈'))// true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈'))// true
console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈哈'))// false
- 字符类(比如\d表示0~9)
(1) [ ]匹配字符集合
后面的字符串只要包含abc中任意一个字符,都返回true。
// 字符类 [abc] 只选1个
console.log(/^[abc]$/.test('a')) // true
console.log(/^[abc]$/.test('b')) // true
console.log(/^[abc]$/.test('c')) // true
console.log(/^[abc]$/.test('ab')) // false
console.log(/^[abc]{2}$/.test('ab')) // true
(2) [ ]里面加上-连字符
使用连字符 - 表示一个范围
[a-z]表示a到z26个英文字母都可以
[a-zA-Z]表示大小写都可以
[0-9]表示0~9的数字都可以
// 字符类 [a-z] 只选1个
console.log(/^[A-Z]$/.test('p')) // false
console.log(/^[A-Z]$/.test('P')) // true
console.log(/^[0-9]$/.test(2)) // true
console.log(/^[a-zA-Z0-9]$/.test(2)) // true
console.log(/^[a-zA-Z0-9]$/.test('p')) // true
console.log(/^[a-zA-Z0-9]$/.test('P')) // true
(3) [ ]里面加上^取反符号
比如:
[^a-z]匹配除了小写字母以外的字符
注意要写到中括号里面
(4) . 小数点匹配除换行符之外的任何单个字符
用户名验证案例:
需求:用户名要求用户英文字母,数字,下划线或者短横线组成,并且用户名长度为6~16位
分析:
①:首先准备好这种正则表达式模式/^[a-zA-Z0-9-_]{6,16}$/
②:当表单失去焦点就开始验证
③:如果符合正则规范,则让后面的span标签添加right类
④:如果不符合正则规范,则让后面的span标签添加wrong类.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
span {
display: inline-block;
width: 250px;
height: 30px;
vertical-align: middle;
line-height: 30px;
padding-left: 15px;
}
.error {
color: red;
background: url(./images/error1.png) no-repeat left center;
}
.right {
color: green;
background: url(./images/right.png) no-repeat left center;
}
</style>
</head>
<body>
<input type="text">
<span></span>
<script>
// 1. 准备正则
const reg = /^[a-zA-Z0-9-_]{6,16}$/
const input = document.querySelector('input')
const span = input.nextElementSibling
input.addEventListener('blur', function () {
// console.log(reg.test(this.value))
if (reg.test(this.value)) {
span.innerHTML = '输入正确'
span.className = 'right'
} else {
span.innerHTML = '请输入6~16位的英文数字下划线'
span.className = 'error'
}
})
</script>
</body>
</html>
预定义:指的是某些常见模式的简写方式
预定类 | 说明 |
\d | 匹配0-9之间的任一数字,相当于[0-9] |
\D | 匹配所有0-9以外的字符,相当于[^0-9] |
\w | 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9] |
\W | 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_] |
\s | 匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f] |
\S | 匹配非空格的字符,相等于[^\t\r\n\v\f] |
日期格式:^\d{4}-\d{1,2}-\d{1,2}
15.4修饰符
修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
语法:
/表达式/修饰符
i是单词ignore的缩写,正则匹配时字母不区分大小写
g是单词global的缩写,匹配所有满足正则表达式的结果
const str = 'java是一门编程语言, 学完JAVA工资很高'
const re = str.replace(/java/ig, '前端') // 前端是一门编程语言, 学完前端工资很高
const re = str.replace(/java/i, '前端') //前端是一门编程语言, 学完JAVA工资很高,只能替换第一个
const re = str.replace(/java/g, '前端') //前端是一门编程语言, 学完JAVA工资很高,只能替换小写java
const re = str.replace(/java | Java/g, '前端')// 前端是一门编程语言, 学完前端工资很高
console.log(re)
过滤敏感字
需求:要求用户不能输入敏感字
比如,pink老师上课很有**
分析:
①:用户输入内容
②:内容进行正则替换查找,找到敏感词,进行**
③:要全局替换使用修饰符g
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>提交</button>
<div></div>
<script>
const tx = document.querySelector('textarea')
const button = document.querySelector('button')
const div = document.querySelector('div')
button.addEventListener('click', function () {
const after =tx.value.replace (/激情|激情/g,'**')
div.innerHTML = after
//提交后表单为空
tx.value = ''
})
</script>
</body>