防抖、节流、重绘、回流、调试 | 青训营

109 阅读4分钟

debounce防抖,原理很简单,设置一个定时器,只执行一次

<body>
    <input type="text" name="" id="text">
    <div id="box"></div>
    
    <!-- 防抖debounce
      
    个人理解:一直触发不会执行,结束执行一段时间后再执行
    指的是:触发事件后在n秒内函数只执行一次,如果在n秒内重复执行了事件,则会重新计算函数执行的时间
    //例子;函数10秒内执行一次,如果在10秒内容重复执行,第9秒还在执行,冲重新按10秒来算 -->
 
 
    <script>
        // 防抖debounce函数
 
         // 参数1:debounce函数被调用的函数(下文的input事件)
         // 参数2: 等待时间   
        function debounce (callback,await) {
            var obj;//定义对象
            var timer=null;//定义定时器
            var fn=function(){
                //将回调函数的this,指向事件源,通过obj保存this指向,达到改变this
                callback.apply(obj)
            }
            return function () {
                //事件源 input
                console.log(this);
                //obj的this指向事件源
                obj=this
                // 如果输入为空的,就清除定时器
                if(timer){
                    clearTimeout(timer)
                }
                // 执行定时器
                timer=setTimeout(fn,await)
            }
        }
        var text=document.getElementById('text')
        var box=document.getElementById('box')
 
        // input框的input事件
        // text.addEventListener('input',function () {
        //     box.innerHTML=text.value
        // })
 
        // 设置一个防抖函数
         text.addEventListener('input',debounce(function () {
            box.innerHTML=text.value
        },5000),false)
        //而第三个参数就是事件的捕获与冒泡, 为true时捕获,false时冒泡。
 
    </script>
</body>

npm有插件 lodash.debounce - npm 防抖函数

cmd安装

npm i --save lodash.debounce

引入模块

var debounce = require('lodash.debounce');

vue 项目中引入模块

import debounce from "lodash.debounce"

节流

<body>
    <input type="text" name="" id="text">
    <div id="box"></div>
    <!-- 节流thorttle
    指的是:连续触发事件但是在n秒中只执行一次函数,节流会稀释函数的执行频率
    个人理解:不管触发多少次,在一段时间内,只执行一次 -->
 
    <script>
        // 节流thorttle函数
 
        // 参数1:thorttle函数被调用的函数(下文的input事件)
        // 参数2: 等待时间   
        function thorttle(callback, await) {
            var obj;//定义对象
            var timer = null;//定义定时器
            var fn = function () {
                //将回调函数的this,指向事件源,通过obj保存this指向,达到改变this
                callback.apply(obj)
            }
            //获取当前的事件
 
            //获取时时间戳  执行函数时间
            //方法1:
            //var nowTime=new Date().getTime()
            //方法2:
            var nowTime = Date.now()
            return function () {
                obj = this
                // 触发函数时间
                var runtime = Date.now()
                // 执行函数时间-触发函数时间-设置等待时间
                var timecha = runtime - nowTime - await
                //如果大于0,就执行这个函数
                if (timecha >= 0) {
                    nowTime = runtime
                    timer = setTimeout(fn, await)
 
                }
            }
        }
        var text = document.getElementById('text')
        var box = document.getElementById('box')
 
        // 设置一个节流函数
        text.addEventListener('input', thorttle(function () {
            box.innerHTML = text.value
        }, 2000), false)
        //而第三个参数就是事件的捕获与冒泡, 为true时捕获,false时冒泡。
    </script>
</body>

防抖

原因:任务频繁触发

原理:任务触发后的间隔时间超过指定的时间,任务才会执行

节流

原理:到了指定的时间就会触发事件,减少执行次数

回流/重排 

当Dom的变化影响到了元素的几何属性(宽和高等)就会触发 

 什么时候会触发? 

添加和或者删除可见的DOM元素 元素的位置发生变化 

元素的尺寸发生变化(包括:外边距,内边距,边框厚度,宽度,高度等属性发生改变) 

内容发生变化(例如:内容增加引起高度变化或者是图片被另外一个不同尺寸的图片所替换) 页面渲染器进行初始化的 

浏览器窗口尺寸发生改变 

重绘 

并不是所有的Dom变化会影响元素的几何属性重绘,如改变 字体颜色、背景颜色等不影响布局的元素样式时,就形成了重绘 

当Dom的变化影响到了元素的几何属性(宽和高等)——比如说修改了边框的宽度,或者是修改了高度,又或者给文章增加了内容导致元素的高度增加等,会引起浏览器进行重新计算元素的几何属性,同样,其他元素的几何属性和位置也会因此受到影响。

浏览器会使渲染树中受到影响的部分失效。并重新构建渲染树,这个过程称为重排。完成重排之后,浏览器会重新绘制受影响的元素,这个过程被称为重绘。

并不是所有的Dom变化会影响元素的几何属性,例如,改变背景色,不会影响元素的几何属性,因此,这个时候是不会发生重排,仅仅会发生重绘,因为,元素的不布局没有发生变化。

重排和重绘的代价都是昂贵的操作,他们会导致浏览器的UI线程卡顿,因此尽可能避免这类操作。 

调试

设置断点

要开始调试代码,首先要做的就是设置断点,断点就是代码执行暂停以便调试它的逻辑点。

DevTools 允许我们以不同的方式来设置断点:

在代码行;

在条件语句中;

在 DOM 节点处;

在事件侦听器上。

1. 在代码行设置断点

设置代码行断点的步骤:

单击切换到 Sources 选项卡;

从文件导航部分选中需要调试的源文件;

在右侧代码编辑器区域找到需要调试的代码行;

单击行号以在行上设置断点。

2、设置条件断点

设置条件断点的步骤:

单击切换到 Sources 选项卡;

从文件导航部分选中需要调试的源文件;

在右侧代码编辑器区域找到需要调试的代码行;

右键单击行号并选择"Add conditional breakpoint"来添加条件断点:

3、在事件监听器上设置断点

在事件监听器上设置断点的步骤:

单击切换到 Sources 选项卡;

在debugger区域展开Event Listener Breakpoints选项;

从事件列表中选择事件监听器来设置断点。我们的程序中有一个按钮单击事件,这里就选择 Mouse 事件选项中的click。

4. 在 DOM 节点中设置断点

DevTools 在 DOM 检查和调试方面同样很强大。当在 DOM 中添加、删除或者修改某些内容时,可以设置断点来暂停代码的执行。

在 DOM 上设置断点的步骤:

单击切换到 Elements 选项卡;

找到要设置断点的元素;

右键单击元素以获得上下文菜单,选择Break on选项,然后选择Subtree modifications、Attribute modifications、Node removal中的一个即可:

1. 下一步(快捷键:F9)

此选项使我们能够在JavaScript代码执行时逐行执行,如果中途有函数调用,单步执行也会进入函数内部,逐行执行,然后退出。

2. 跳过(快捷键:F10)

此选项允许我们在执行代码时跳过一些代码。有时我们可能已经确定某些功能是正常的,不想花时间去检查它们,就可以使用跳过选项。

3. 进入(快捷键:F11)

使用该选项可以更深入地了解函数。单步执行函数时,当感觉某个函数的行为异常并想检查它时,就可以使用这个选项来进入函数内部并进行调试。

4. 跳出(快捷键:Shift+F11)

在单步执行一个函数时,我们可能不想再继续执行并退出它,就可以使用这些选项退出函数。

5. 跳转(快捷键:F8)

有时,我们希望从一个断点跳转到另一个断点,而无需在它们之间进行任何调试,就可以使用这个选项来跳转到下一个断点: