zoukankan      html  css  js  c++  java
  • 浅谈 JS 的防抖和节流

    浅谈 JS 的防抖和节流

    前言:在了解防抖和节流之前,我们来认识聚焦事件和键盘事件

    一、聚焦事件 (focus、blur、input)

    • FocusEvent事件

      焦点事件主要用于表单元素,以及超链接,使用点击或者tab可以切换汇聚焦距,当input聚焦是触发focus,失去焦点时触发blur

      • foucs 是汇聚焦距 一般汇聚焦距时,会有outline样式
      • blur 失去焦点
      • 事件对象中relatedTarget为上一个失去焦点对象
        <form>
            <input type="text">
            <input type="checkbox">
            <input type="checkbox">
            <select>
                <option>aaaa</option>
                <option>bbb</option>
                <option>aaaa</option>
                <option>aaaa</option>
                <option>aaaa</option>
            </select>
        </form>
        <a href="#">超链接</a>
        <script>
                    var form=document.querySelector("form");
            var input=document.querySelector("input");
            input.addEventListener("focus",focusHandler);
            input.addEventListener("blur",focusHandler);
    
            // 获取单选按钮
            var checkboxs=document.querySelectorAll("[type=checkbox]");
            for(var i=0;i<checkboxs.length;i++){
                checkboxs[i].addEventListener("focus",focusHandler)
            }
    
            // 获取下拉列表
            var select=document.querySelector("select");
            select.addEventListener("focus",focusHandler);
    
            //获取超链接
            var a=document.querySelector("a");
            a.addEventListener("focus",focusHandler)
    
            function focusHandler(e){
                console.log(e.target,e);
                if(e.type==="focus"){
                    e.target.style.outline="1px solid purple"
                    e.target.style.outlineOffset="0px";
                }else if(e.type==="blur"){
                    e.target.style.outline="1px solid rgba(255,0,0,0)";
                    e.target.style.outlineOffset="5px";
                }
            }
    
    
        </script>
    
    

    失焦和聚焦主要用来判断表单验证

            // input  输入事件主要用于文本框和多行文本框
    
            var input=document.querySelector("input");
            input.addEventListener("input",inputHandler);
    
            function inputHandler(e){
               console.log(e);
            // e.data: "s"  本次输入的内容
            // e.isComposing: false  输入法是否启动
            // e.inputType 输入的类型
            // insertCompositionText 输入插入
            // historyUndo 历史返回
            // insertText  插入文本
            // deleteContentBackward 退格删除(删除前一个)
            // deleteContentForward  delete删除(删除后一个)
            // deleteByCut 剪切删除
            // insertFromPaste 粘贴插入
          }
    
    

    二、KeyboardEvent 键盘事件

        <div></div>
        <script>
            var bool=false
            // 按键是侦听document
            document.addEventListener("keydown",keyHandler);
            document.addEventListener("keyup",keyHandler);
            // keydown不单纯在按下时存在,一直按着也会触发
            function keyHandler(e){
                if(e.type==="keydown"){
                    // 希望在什么地方加开关,这个开关指锁定这个位置
                    if(!bool){
                        console.log(e.type,e.keyCode);
                    }
                    bool=true;
                    return;
                }else{
                    bool=false;
                }
                console.log(e.type,e.keyCode);
                // e.code: "KeyJ"  键名
                // key: "j"   键名
                // keyCode: 74  键码
                // which   键码
                // 左 上 右 下  37,38,39,40
            }
    

    1、节流

    文本框在输入的时候,如果每输入一次就判断一次,会造成效率太低,我们让它每间隔一段时间,再去验证。即指连续触发事件但是在 n 秒中只执行一次函数。

    实现原理

    给 input 设置一个属性,第一次触发事件时,属性值为 false,则往下执行,500毫秒后获取 input 的值,同时删除 ids 的值;第二次输入时,当500毫秒还没到时,ids 为 true ,则直接跳出,不去获取 value 值 。在500毫秒中,只执行一次函数。

    节流的定时器写法:

    <input type="text" name="text" id="user">
    <script>
    	init();
    	function init(){
    	    var user=document.getElementById("user");
    	     user.addEventListener("input",inputHandler);
    	}
    	function inputHandler(e){
    	    //判断,如果input.ids为false,则往下执行
    	    if(this.ids) return;
    	    //500毫秒后,执行showValue函数,同时删除ids的值
    	    this.ids=setTimeout(function(elem){
    	    	//因为定时器函数会改变this指向,这里将this以参数的形式传进来
    	        clearTimeout(elem.ids);
    	        elem.ids=null;
    	        showValue(elem.value);
    	    },500,this);
    	}
    	//打印出input的值
    	function showValue(txt){
    	    console.log(txt);
    	}
    </script>
    

    节流的时间戳写法:

    <input type="text" name="text" id="user">
    <script>
    	init();	
    	function init() {
    	    var user = document.getElementById("user");
    	    user.addEventListener("input", inputHandler);
    	}
    	var lastTime=0;
    	function inputHandler(e) {
    	    //每次触发事件获取当前时间
    	   let nowTime=new Date().getTime();
    	   //若时间间隔大于500毫秒,则执行代码
    	   if(nowTime-lastTime>500){
    	       //重新计时
    	       lastTime=nowTime;
    	       showValue(this.value);
    	   }
    	}
    	//打印出input的值
    	function showValue(txt) {
    	    console.log(txt);
    	}
    </script>
    
    

    2.防抖

    防抖就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
    keydown事件,当键盘按下时触发,如果键盘一直按下,则会一直触发这个事件,我们并不希望在事件持续触发的过程中那么频繁地去执行函数。这种情况防抖是比较好的解决方案。

    实现原理

    当持续触发keydown事件时,事件处理函数handle只在停止按键500毫秒之后才会调用一次,也就是说在持续触发keydown事件的过程中,事件处理函数handle一直没有执行。

    节流和防抖有相似之处,我们在上面节流的基础上,该成下面的代码

    <input type="text" name="text" id="user">
    <script>
    	init();
    	function init() {
    	    var user = document.getElementById("user");
    	    user.addEventListener("input", inputHandler);
    	}
    	var ids=null;
    	function inputHandler(e) {
    		//每次输入,把前面的定时器清除,重新开启定时器
    	    if(ids !== null) clearTimeout(ids);
    	    ids=setTimeout(function(){
    	        showValue(this.value);
    	    },500)
    	}
    	//打印出input的值
    	function showValue(txt) {
    	    console.log(txt);
    	}
    </script>
    
    

    防抖封装

     function debounce(fn, wait) {
        var timeout = null; //定义一个定时器
        return function () {
            if (timeout !== null)
                clearTimeout(timeout); //清除这个定时器
            timeout = setTimeout(fn, wait);
        }
    }
    // 处理函数
    function handle() {
        console.log(Math.random());
    }
    // 侦听事件
    document.addEventListener("keydown", debounce(handle, 1000));
    
    

    防抖和节流的区别?

    • 节流是将多次执行变为每隔一段时间执行
    • 防抖是将多次执行变为最后一次执行
  • 相关阅读:
    给暗黑2佣兵换装备,他/她说的英语是什么?
    为什么“家徒四壁”中的徒是仅仅,只有的意思?
    喜马拉雅几个有意思的订阅内容
    看似最艰苦的道路,长远考虑确是收益最大,实际上最容易的路
    《赠友》--杜运夑
    【Python】由host得到IP
    day31_Hibernate复习_03(补刀)
    day31_Hibernate复习_03
    day31_Hibernate学习笔记_03
    MyEclipse2017 CI 断点无效
  • 原文地址:https://www.cnblogs.com/my12-28/p/12655481.html
Copyright © 2011-2022 走看看