计时器方法

setInterval

每个一段时间执行一次函数

        setInterval(() => {
            console.log("hello")
        },1000)//每间隔一秒打印hello

在网页中显示当前时间

    <h1></h1>
    <script>
        let h1 = document.querySelector("h1");
        setInterval(()=>{
            let timeNow = new Date();
            let hours = timeNow.getHours()<10?"0"+timeNow.getHours():timeNow.getHours();//个位数前面补0
            let minutes = timeNow.getMinutes()<10?"0"+timeNow.getMinutes():timeNow.getMinutes();
            let seconds = timeNow.getSeconds()<10?"0"+timeNow.getSecondes():timeNow.getSeconds();
            let time = `${hours}:${minutes}:${seconds}`;
            h1.innerText = time;
        },1000)
    </script>

clearInterval

    <button class="start">开始</button>
    <button class="end">暂停</button>
    <script>
        let btn1 = document.querySelector(".start")
        let btn2 = document.querySelector(".end")

        let timer
        //定时器的对象是window,需要全局声明才能通过函数调用
        //如清除定时器的函数clearInterval调用定时器btn1里的setInterval
        btn1.addEventListener("click",function(){
            console.log("start")
            timer = setInterval(() => {
            console.log("hello")
        },1000)
        })

        btn2.addEventListener("click",function(){
            clearInterval(timer);
            console.log("stop")
        })
    </script>

制作秒表(开始、暂停、结束)

<body>
    <button class="start">开始</button>
    <button class="pause">暂停</button>
    <button class="end">结束</button>
    <h1 class="time"></h1>
    <script>
        let start = document.querySelector(".start");
        let pause = document.querySelector(".pause");
        let end = document.querySelector(".end");
        let time = document.querySelector(".time");
        let minutes = 0;
        let seconds = 0;
        let ms = 0;//不是真正意义上的毫秒,实际是10ms
        let timer = null;

        time.innerHTML = `${minutes}:${seconds<10?"0"+seconds:seconds}:${ms<10?"0"+ms:ms}`;

        start.addEventListener("click",function(){
            clearInterval(timer);//清除抖动,防止连点“开始”,出现越点越快的情况(多个计数器参与计时)
            timer = setInterval(() => {
                if(seconds === 60){
                    seconds = 0;//先归零,不然会出现秒数为60的情况
                    ++minutes;
                }
                if(ms === 100){
                    ms = 0;//重置ms,10毫秒为单位速度过快,有时还是会出现ms数为100
                    ++seconds;
                }
                ++ms;
                time.innerHTML = `${minutes}:${seconds<10?"0"+seconds:seconds}:${ms<10?"0"+ms:ms}`;
            },10)//10ms触发一次,1秒触发100次,实现ms逢100进1s
        })

        pause.addEventListener("click",function(){
            clearInterval(timer);
        })

        end.addEventListener("click",function(){
            clearInterval(timer);//没有暂停会导致计时器继续工作更新innerHtml,时间归零无效
            minutes = 0;
            seconds = 0;
            ms = 0;
            time.innerHTML = `${minutes}:${seconds<10?"0"+seconds:seconds}:${ms<10?"0"+ms:ms}`;
        })

    </script>
</body>
</html>

setTimeout

过多少秒后只执行一次

        setTimeout(() => {
            console.log("hello")
        },3000)//3s后输出一次hello

3s后跳转到百度

    <h1>3s后跳转到百度</h1>
    <script>
        setTimeout(() => {
            location.href = "http://baidu.com"//跳转链接
        },3000)
    </script>

clearTimeout

停止setTimeout计时器

    <button>停止</button>
    <script>
        let btn = document.querySelector("button")
        let timer = null;
        timer = setTimeout(() => {
            console.log("hello")
        },3000)

        btn.addEventListener("click",function(){
            clearTimeout(timer)
        })
    </script>

防抖与节流

防抖debounce

    <style>
        body{
            height: 2000px;
        }
    </style>
</head>
<body>
    <h1>window.onscroll事件</h1>
    <script>
        window.onscroll = function(){//鼠标滚轮触发事件
            console.log("hello")
        }
    </script>
</body>


可见,鼠标上下滚了一遍,打印hello执行了160次,如果事件是其他的复杂逻辑,那就会耗费大量的性能,因此要防抖

    <h1>window.onscroll事件</h1>
    <script>
        let timer = null;
        window.onscroll = function(){
            if(timer !== null){
                clearTimeout(timer)
            }
            timer = setTimeout(() => {
                console.log("hello")
                timer = null
            },500)
            /*timer默认是null,则滚动后直接执行timer=setTimerout,但一执行该语句,timer马上就有了值,!=null
            所以又会被clearTimeout停止计时。接着继续执行timer=setTimerout,又被停止计时。
            只要鼠标一直处于滚动状态,计时器就会一直被暂停。直到鼠标不滚动了,最后一次clearTimeout
            接着timer=setTimerout,这次因为已经不触发onscrll事件了,所以程序不会回到if判断
            而是继续执行计时器,0.5s后输出hello
            宏观上看,就是在鼠标滚动开始到停止滚动,0.5s后才输出一次hello
            不会出现鼠标滚动就一直输出hello的情况,防抖*/
        }
    </script>

节流throttle

按照时间间隔触发事件

      <h1>window.onscroll事件</h1>
    <script>
        let mark = true;
        window.onscroll = function(){
            if(mark){
                setTimeout(() => {
                    console.log("hello");
                    mark = true;
                },500);
            }
            mark = false;
            /*if事件执行了但计时器还没执行,在计时器执行前mark=false,再滚动也不会执行新的计时器
            0.5s后计时器执行,输出hello,mark=true
            滚动鼠标又能执行if语句,一直往复
            即管鼠标一直滚动,每0.5s才执行输出一次hello*/
        }
    </script>

练习

返回顶部

    <style>
        button{
            position: fixed;
            right: 100px;
            bottom: 100px;
            display: none;
        }
        body{
            height: 2000px;
        }
    </style>

<body>
    <h1>hello world</h1>
    <button>↑</button>
    <script>
        let btn = document.querySelector("button")
        btn.onclick = function(){
            window.scrollTo(0,0)//横向纵向滚动条位置为最左边和最上边
        }
        let timer = null;
        window.onscroll = function(){
            if(timer !== null){
                clearTimeout(timer);
            }
            timer = setTimeout(() => {
                console.log("计数器");
            //document.documentElement.scrollTop滚动条距离顶部的距离
                if(document.documentElement.scrollTop > 0){
                btn.style.display = "block";
                }else{
                btn.style.display = "none";
                timer = null;
            }
            },500)
        }
    </script>
</body>
</html>

改进,利用闭包封装防抖算法

    <script>
        let btn = document.querySelector("button");
        btn.onclick = function(){
            window.scrollTo(0,0)
        }
        function debounce(fn){//闭包的意义在于把防抖的算法和业务算法区分开来
            let timer = null;
            function eventFun(){
                if(timer !== null){
                 clearTimeout(timer);
                }
                timer = setTimeout(() => {
                    //业务逻辑在这,用一个函数fn表示
                    fn();
                    timer = null;
                },500)
            }
            return eventFun;
        }
        window.onscroll = debounce(() => {//把业务逻辑传给fn
                console.log("计数器");
                //document.documentElement.scrollTop滚动条距离顶部的距离
                if(document.documentElement.scrollTop > 0){
                btn.style.display = "block";
                }else{
                btn.style.display = "none";
                timer = null;
            }
        });
    </script>

把防抖改成节流

    <script>
        let btn = document.querySelector("button");
        btn.onclick = function(){
            window.scrollTo(0,0)
        }
        function throttle(fn){
            let mark = true;
            return function(){
                if(mark){
                    setTimeout(() => {
                        fn();
                        mark = true;
                    },500)
                }
                mark = false;
            }
        }
        window.onscroll = throttle(() => {
                console.log("计数器");
                if(document.documentElement.scrollTop > 0){
                btn.style.display = "block";
                }else{
                btn.style.display = "none";
                timer = null;
            }
        });
    </script>
posted @ 2022-10-31 21:30  ben10044  阅读(133)  评论(0编辑  收藏  举报