定时器/事件

定时器

网页中经常会需要:每隔一段时间需要自动执行一段代码,不需要我们手动去触发 -----定时器函数

比如:网页中得倒计时

定时器函数有两种:间隔函数延迟函数

间隔函数

作用:每隔指定的时间 自动重复执行某些代码

定时器函数可以开启关闭定时器

开启定时器

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">&lt;</button>
            <button class="right">&gt;</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中注册事件的常用技巧,也称为事件委派,事件代理

原本需要注册在子元素的事件委托给父元素,让父元素担当事件监听的职务

为什么? 同时给多个元素注册事件,需要利用循环多次注册事件

事件委托是利用事件流的特征解决一些开发需求

优点:减少注册次数,提高程序性能

原理:事件委托其实就是利用事件冒泡的特点

给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件

<!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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值