定时器
网页中经常会需要:每隔一段时间需要自动执行一段代码,不需要我们手动去触发 -----定时器函数
比如:网页中得倒计时
定时器函数有两种:间隔函数 和 延迟函数
间隔函数
作用:每隔指定的时间 自动重复执行某些代码
定时器函数可以开启和关闭定时器
开启定时器
setInterval(函数名,间隔时间) //函数名不能加括号
每隔一段时间调用这个函数 ,间隔时间单位是毫秒
关闭定时器
clearInterval(timer)
//timer是定时器变量名 返回的是一个唯一的数字
定时器案例
<script>
// 1. 初始数据
const sliderData = [
{ src: './img/quality03.png', title: '第1张图片', color: 'rgba(100, 67, 68,.3)' },
{ src: './img/quality04.png', title: '第2张图片', color: 'rgba(43, 35, 26,.3)' },
{ src: './img/quality05.png', title: '第3张图片', color: 'rgba(36, 31, 33,.3)' },
{ src: './img/quality06.png', title: '第4张图片', color: 'rgba(139, 98, 66,.3)' },
{ src: './img/quality07.png', title: '第5张图片', color: 'rgba(67, 90, 92,.3)' },
]
// 1. 获取元素
const img = document.querySelector('.slider-wrapper img')
const p = document.querySelector('.slider-footer p')
const footer = document.querySelector('.slider-footer')
// 2.开启定时器
let i = 0 // 信号量 控制图片张数
// console.log(sliderData[i])
setInterval(function () {
i++
// 无缝衔接位置 一共5张图片,到了最后一张就是 5,数组的长度就是 5
if (i >= sliderData.length) {
i = 0
}
// console.log(sliderData[i])
img.src = sliderData[i].url
p.innerHTML = `${sliderData[i].title}`
footer.style.backgroundColor = `${sliderData[i].color}`
//小圆点
//先删除以前的 active
document.querySelector('.slider-indicator .active').classList.remove('active')
//只让当前 li 添加 active
document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
}, 1000)
</script>
事件监听
以前写的代码都是自动执行的,我们希望一段代码在某个特定的时机才去执行
- 点击按钮可以弹出提示框
- 鼠标经过显示下拉菜单
事件
事件是程序在运行的时候,发生的特定动作或者特定的事情比如点击按钮,鼠标经过菜单…
语法
元素对象.addEventListener('事件类型',事件处理函数)
1.事件发生后,想要执行的代码写到事件处理函数
2.触发指定的事件时,事件处理函数就会执行
3.事件监听是将事件处理函数注册到元素对象身上
4.事件监听也称为:事件注册、事件绑定
事件监听三要素:
-
事件源
谁被触发了 ,那个元素上触发
-
事件类型
鼠标点击click,鼠标经过mouseenter等
-
事件处理函数
要做什么事情,把要做的事情放到事件处理函数里面
回调函数
一个函数作为参数传递给另外一个函数的时候,这个函数就是回调函数
回调函数本质还是函数,只不过把它作为参数使用
作用:完成某些特定的任务
使用场景
//使用匿名函数作为回调函数
setInterVal(function(){
//执行特定的任务 切换轮播图图片
},1000)
addEventListener('click',function(){
//执行特定的任务 弹出提示框
})
事件监听版本
L: level 标准 层次
// DOM L0
事件源.on事件类型= function(){}
btn.onclick=function(){
alert("我是弹框")
}
//DOM L2
事件源.addEventListener(事件类型,事件处理函数)
btn.addEventListener('click',function(){
alert('我是弹框')
})
// 事件监听版本
const btn = document.querySelector('button');
// DOM L0 注册同名事件,会出现覆盖情况
// btn.onclick = function(){
// alert("我是弹窗");
// }
// btn.onclick = function(){
// alert("我是弹窗2");
// }
// DOM L2 注册同名click事件 不会出现覆盖情况
btn.addEventListener('click',function(){
alert("我是弹窗")
})
btn.addEventListener('click',function(){
alert("我是弹窗2");
})
事件类型
事件类型统一用小写字母
鼠标事件
click鼠标点击
mouseenter 鼠标经过
mouseleave 鼠标离开
// 鼠标事件类型
const box = document.querySelector('.box');
// 鼠标点击
// box.addEventListener('click',function(){
// alert("我点击了盒子");
// })
// 2.鼠标经过
// box.addEventListener('mouseenter',function(){
// console.log("我鼠标经过了盒子");
// })
// 3.鼠标离开
box.addEventListener('mouseleave',function(){
console.log("我鼠标离开了盒子");
})
轮播图完整版案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.slider .slider-wraper {
position: relative;
width: 228px;
height: 156px;
margin: 0 auto;
}
.slider .slider-wraper .img-wraper {
height: 156px;
overflow: hidden;
}
.slider-wraper img {
border-radius: 5px;
}
.footer {
width: 228px;
height: 50px;
position: relative;
bottom: 50px;
border-radius: 0 0 5px 5px;
background-color: rgba(100, 67, 68, .3);
}
.slider-wraper .footer p {
font-size: 12px;
color: #fff;
margin-bottom: 10px;
margin-left: 15px;
}
.slider-wraper .left,
.slider-wraper .right {
position: absolute;
border: none;
background-color: rgba(233, 233, 233, .2);
}
.slider-wraper .left,
.slider-wraper .right:hover {
cursor: pointer;
}
.slider-wraper .left {
left: 0;
bottom: 50%;
transform: translateY(50%);
}
.slider-wraper .right {
right: 0;
bottom: 50%;
transform: translateY(50%);
}
ul {
display: flex;
align-items: center;
margin-left: 15px;
}
li {
list-style: none;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #ccc;
margin-right: 5px;
}
li:hover {
cursor: pointer;
}
.active {
width: 7px;
height: 7px;
background-color: #fff;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="slider">
<div class="slider-wraper">
<div class="img-wraper">
<img src="./img/quality03.png" alt="">
</div>
<div class="footer">
<p>第1张图片</p>
<ul>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<button class="left"><</button>
<button class="right">></button>
</div>
</div>
<script>
const imgdata = [
{ src: './img/quality03.png', title: '第1张图片', color: 'rgba(100, 67, 68,.3)' },
{ src: './img/quality04.png', title: '第2张图片', color: 'rgba(43, 35, 26,.3)' },
{ src: './img/quality05.png', title: '第3张图片', color: 'rgba(36, 31, 33,.3)' },
{ src: './img/quality06.png', title: '第4张图片', color: 'rgba(139, 98, 66,.3)' },
{ src: './img/quality07.png', title: '第5张图片', color: 'rgba(67, 90, 92,.3)' },
]
const img = document.querySelector('.slider-wraper img')
const sliderWraper = document.querySelector('.slider-wraper')
const lis = document.querySelectorAll('.footer ul li')
const p = document.querySelector('.footer p')
const footer = document.querySelector('.footer')
const btnl = document.querySelector('.slider-wraper .left')
const btnr = document.querySelector('.slider-wraper .right')
let i = 0 // 信号量 控制播放图片张数
// 封装切换轮播图的函数
function toggle() {
img.src = imgdata[i].src
p.innerHTML = imgdata[i].title
footer.style.backgroundColor = imgdata[i].color
document.querySelector('.slider-wraper .footer ul .active').classList.toggle('active')
lis[i].classList.add('active')
}
// 开启定时器
let timer = setInterval(function () {
i++
// if (i >= imgdata.length) {
// i = 0
// }
// i = i >= imgdata.length ? 0 : i
i = i % imgdata.length
toggle()
}, 1000)
// 鼠标经过时,停止计时器
sliderWraper.addEventListener('mouseenter', function () {
clearInterval(timer)
})
// 鼠标离开时,开启计时器
sliderWraper.addEventListener('mouseleave', function () {
clearInterval(timer)
timer = setInterval(function () {
// 每隔一秒,自动点击一次右侧按钮
btnr.click()
}, 1000)
})
// 点击小圆点跳转模块
for (let j = 0; j < lis.length; j++) {
lis[j].addEventListener('click', function () {
i = j
toggle()
})
}
// 左右按钮点击跳转模块
btnl.addEventListener('click', function () {
console.log('点击左按钮');
i--
// if (i < 0) {
// i = imgdata.length - 1
// }
i = (i + imgdata.length) % imgdata.length
toggle()
})
btnr.addEventListener('click', function () {
console.log('点击右按钮');
i++
// if (i > imgdata.length - 1) {
// i = 0
// }
i = i % imgdata.length
toggle()
})
</script>
</body>
</html>
焦点事件
focus获得焦点
blur 失去焦点
<body>
<input type="text" class="search-text">
<input type="text" class="search">
<script>
// 焦点事件 (手动触发)
const search_text = document.querySelector(".search-text");
// 获取焦点
search_text.addEventListener('focus',function(){
console.log("获得了焦点");
})
// 失去焦点
search_text.addEventListener('blur',function(){
console.log("失去焦点");
})
// 自动获得焦点 focus() 自动失去焦点 blur()
// 元素.focus()
const search= document.querySelector('.search')
search.focus()
</script>
</body>
小米搜索框显示隐藏案例
<!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>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.mi {
position: relative;
width: 230px;
margin: 100px auto;
}
.mi .search-text {
width: 230px;
height: 48px;
padding: 0 10px;
font-size: 14px;
line-height: 48px;
border: 1px solid #ccc;
outline: none;
}
.result-list {
display: none;
position: absolute;
left: 0;
top: 48px;
width: 228px;
border: 1px solid red;
border-top: 0;
background-color: #fff;
}
.result-list a {
display: block;
padding: 6px 15px;
font-size: 12px;
color: #333;
text-decoration: none;
}
.result-list a:hover {
background-color: #eee;
}
.mi .search {
border: 1px solid red;
}
</style>
</head>
<body>
<div class="mi">
<input type="search" placeholder="小米笔记本" class="search-text">
<ul class="result-list">
<li><a href="#">全部商品</a></li>
<li><a href="#">小米1</a></li>
<li><a href="#">小米2</a></li>
<li><a href="#">小米收集</a></li>
<li><a href="#">小米空调</a></li>
</ul>
</div>
<script>
// 1.先隐藏下拉菜单
// 2.获取元素
const search_text = document.querySelector('.search-text');
const result_list = document.querySelector('.result-list');
search_text.addEventListener('focus', function () {
result_list.style.display = 'block';
// 搜索框添加边框颜色
search_text.classList.add('search');
})
search_text.addEventListener('blur', function () {
result_list.style.display = 'none';
search_text.classList.remove('search');
})
</script>
</body>
</html>
键盘事件
keydown 键盘按下
keyup 键盘抬起
<!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>
<style>
textarea {
width: 300px;
height: 30px;
padding: 10px;
border-color: transparent;
outline: none;
background: #f5f5f5;
border-radius: 5px;
}
</style>
</head>
<body>
<textarea id="tx" placeholder="发一条评论"></textarea>
<script>
// 获取元素
const tx = document.querySelector("#tx");
// 键盘事件
// 键盘按下事件 keydown 当我们按下键盘时触发
tx.addEventListener('keydown', function () {
console.log("我是keydown事件", tx.value)
})
// 键盘弹起事件 keyup 当我们键盘弹起的时候触发
tx.addEventListener('keyup', function () {
console.log('keyup事件', tx.value)
})
// 用户输入事件input 表单value值发生变化的时候触发
tx.addEventListener('input', function () {
console.log("我是input事件", tx.value)
})
// 注意事项
// 执行顺序 keydown-->input--->keyup
// keydown 获取值的时候得不到最后一次按键的值 keyup和input可以得到用户输入的内容
</script>
</body>
</html>
文本事件
input 表单value被修改时触发
<!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>
<style>
.wrapper {
width: 400px;
display: flex;
justify-content: flex-end;
}
.wrapper textarea {
flex: 1;
height: 30px;
padding: 10px;
border-color: transparent;
outline: none;
background-color: #f5f5f5;
border-radius: 5px;
transition: all 0.5s;
}
.wrapper textarea:focus {
height: 50px;
border-color: #e4e4e4;
background-color: #fff;
}
.wrapper button {
width: 70px;
margin-left: 10px;
border: none;
color: #fff;
background-color: #f00;
border-radius: 5px;
}
.wrapper .total {
margin-right: 80px;
margin-top: 5px;
color: #888;
opacity: 0;
transition: all 0.5s;
}
</style>
</head>
<body>
<div class="wrapper">
<textarea id="tx" placeholder="发一条评论" maxlength="200"></textarea>
<button>发布</button>
</div>
<div class="wrapper">
<span class="total">0/200字</span>
</div>
<script>
// 文本域获取焦点 让total透明度改为1 失去焦点改为0
const tx = document.querySelector("#tx");
const total = document.querySelector(".total");
// 获取焦点
tx.addEventListener('focus', function () {
total.style.opacity = 1
})
tx.addEventListener('blur', function () {
total.style.opacity = 0
})
// 得到用户输入的字符长度,写到total的盒子里面
// 根据input事件,得到用户的字符长度
tx.addEventListener('input', function () {
console.log(tx.value.length)
// 把字符长度写到total盒子里面
total.innerText = `${tx.value.length}/200字`
})
</script>
</body>
</html>
事件对象
事件对象
是什么
也是个对象,这个对象里有事件触发时的相关信息,包含属性和方法
鼠标点击事件中,事件对象就存了鼠标点击在哪个位置等信息
使用场景
可以判断用户按下哪个键,比如按下回车键-可以发表评论
可以判断鼠标点击了哪个元素,从而做相应的操作
语法
- 注册事件中,回调函数的第一个参数就是事件对象
- 一般命名为event,ev,e
元素.addEventListener('click',function(e){ //e事件对象
})
常见属性
offsetX 事件发生时,鼠标相对于事件源的X坐标
offsetY 事件发生时,鼠标相对于事件源的Y坐标
target 事件源对象
key 如果是键盘相关的事件,则事件对象中包含该属性,表示键盘事件发生时,按下的是什么键,Enter 回车键
pageX 事件发生时,鼠标相对于网页的X坐标
pageY 事件发生时,鼠标相对于网页的Y坐标
clientX 事件发生时,鼠标相对于视口的X坐标
clientY 事件发生时,鼠标相对于视口的Y坐标
环境对象-this
环境对象–指的是函数内部特殊的this,它指向一个对象,并且受当前环境的影响
作用: 很清晰this的指向
- 函数调用方式不同,this指的对象也不同
- 【谁调用,this就是谁】是判断this指向的粗略规则
- 直接调用函数,其实相当于window.函数(), this指的是window
<button>按钮</button>
<script>
// 环境对象 【谁调用函数,this就指向谁】
// 1.全局环境
console.log(this);// this指向window全局对象
// 2.普通函数
function fn() {
console.log(this); //this指向window全局对象
}
window.fn();
// 3.对象方法
const obj = {
uname: "佩奇",
sing: function () {
console.log(this); //this指向obj对象
}
}
obj.sing();
// 4.事件
const btn = document.querySelector('button');
btn.addEventListener('click', function () {
console.log(this) //this指向btn这个对象
// btn.style.backgroundColor = 'pink';
this.style.backgroundColor = 'pink';
})
</script>
排他思想
是一种思想,目的是突出显示某个元素(排除其他人,保留我自己)
比如:有多个元素,鼠标经过时,只有当前元素添加高亮样式,其余元素移除样式
事件流
为什么? 帮我们解决问题—点击盒子会弹出2次的问题
是什么? 事件完整执行过程中的流动路径
触发事件 会经历两个阶段 捕获阶段 冒泡阶段
事件捕获
事件捕获:一个元素的事件被触发时,会从DOM的根元素开始依次调用同名事件(从外到内)
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
第三个参数传入true 代表的是捕获阶段触发(很少使用)
传入false,代表的是冒泡阶段触发 --默认是false
事件冒泡
事件冒泡:一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发(从内到外)
一个元素触发事件后,会依次向上调用所有父级元素的同名事件
传入false,代表的是冒泡阶段触发 --默认是false
事件冒泡是默认存在的。实际工作中使用冒泡居多
阻止冒泡
冒泡是默认存在的,所以容易导致事件影响到父级元素(问题)
想要把事件限制在当前元素内,就需要阻止事件冒泡
事件对象.stopPropagation()
//该方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
鼠标经过/离开事件的区别
- mouseover和mouseout 会有冒泡
- mouseenter 和mouseleave 没有冒泡(常用)
事件委托
是JavaScript中注册事件的常用技巧,也称为事件委派,事件代理
原本需要注册在子元素的事件委托给父元素,让父元素担当事件监听的职务
为什么? 同时给多个元素注册事件,需要利用循环多次注册事件
事件委托是利用事件流的特征解决一些开发需求
优点:减少注册次数,提高程序性能
原理:事件委托其实就是利用事件冒泡的特点文章来源:https://www.toymoban.com/news/detail-515652.html
给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件文章来源地址https://www.toymoban.com/news/detail-515652.html
<!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>
<ul>
<li>第1个孩子</li>
<li>第2个孩子</li>
<li>第3个孩子</li>
<li>第4个孩子</li>
<li>第5个孩子</li>
</ul>
<script>
// 点击每个li都会有弹窗效果
// 获取父元素ul
const ul=document.querySelector('ul');
// 给ul注册事件
ul.addEventListener('click',function(e){
// console.log("弹窗")
// 事件对象.target 得到目标元素
// 获取到当前点击的元素 事件对象.target.tagName 可以获得真正触发事件的元素
console.log(e.target);
// 点击哪个li 对应的li变色
// e.target.style.color ='pink'
// console.dir(e.target)
if(e.target.tagName =='LI'){
e.target.style.color= 'pink'
}
})
</script>
</body>
</html>
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>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
.tab{
width: 600px;
height: 350px;
margin:20px auto;
border: 1px solid #e4e4e4;
}
.tab .tab-nav{
height: 50px;
background-color: pink;
}
.tab .tab-nav ul{
display: flex;
align-items: center;
}
.tab .tab-nav ul li{
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
}
.tab .tab-nav ul li.active{
background-color: red;
color: #fff;
}
.tab .tab-content .item{
display: none;
}
.tab .tab-content .show{
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<ul>
<li class="active" data-id="0">
<a href="#">潮流</a>
</li>
<li data-id="1">
<a href="#">时尚</a>
</li>
<li data-id="2">
<a href="#">收藏</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="item hidden">潮流</div>
<div class="item">时尚</div>
<div class="item">收藏</div>
</div>
</div>
<script>
// 鼠标经过不同的选项卡,底部显示不同的内容
/*
1.给父级ul注册鼠标经过事件,采用事件委托方式
2.注意mouseenter没有冒泡,所以此处使用mouseover
3.排他思想,删除添加类
4.e.target.tagName 来进行判断
*/
// 1.给父级ul注册鼠标经过事件,采用事件委托方式 mouseover
const ul =document.querySelector('.tab-nav ul');
const items = document.querySelectorAll(".tab-content .item")
ul.addEventListener('mouseover',function(e){
// 只有鼠标经过li才会高亮
if(e.target.tagName==='LI'){
document.querySelector('.tab-nav .active').classList.remove('active')
// 当前元素添加active
e.target.classList.add('active')
// 底部跟随
// 因为没有索引号 所以我们要自定义属性 给3个li添加序号
// e.target.dataset.id
// console.log(e.target.dataset.id)
document.querySelector('.tab-content .show').classList.remove('show')
items[e.target.dataset.id].classList.add('show')
}
})
</script>
</body>
</html>
到了这里,关于定时器/事件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!