有关性能优化(包含防抖节流)

有关性能优化(包含防抖节流)

一.性能优化的原则:
在这里插入图片描述
二.性能优化的方案:
1》资源合并:
在这里插入图片描述
2》缓存:
在这里插入图片描述
在这里插入图片描述
3》使用CDN(Content Delivery Network)内容分发网络:

  1. 传统访问
    ①.用户在浏览器输入域名发起请求
    ②.DNS 服务器解析域名获取服务器 IP 地址
    ③.根据 IP 地址找到对应的服务器
    ④.服务器响应并返回数据

  2. CDN 访问
    ①.用户在浏览器输入域名发起请求
    ②.智能 DNS 解析(根据 IP 判断地理位置和网络运营商,选择路由最短和负载最轻的服务器)
    ③.获取缓存服务器 IP 地址
    ④.根据 IP 地址找到对应的缓存服务器
    ⑤.如果缓存命中,则响应并返回数据;如果缓存未命中,则向源站点发起请求
    ⑥.源站点返回数据,并在缓存服务器缓存一份数据

  3. CDN 优势
    ①,本地缓存加速,提高企业站点的访问速度
    ②.跨运营商的网络加速,保证不同网络的用户都能得到良好的访问质量
    ③.广泛分布的 CDN 节点加上节点之间的智能冗余机制,可以有效的预防黑客入侵

  4. 实际应用
    ①.我们在引入bootstrap等框架时,也会引入CDN地址
    在这里插入图片描述
    ②.百度的好多js文件,都用的是static静态服务,都是用CDN做的
    在这里插入图片描述

4》使用SSR(server side render)服务器渲染:
在这里插入图片描述
5》懒加载:
在这里插入图片描述
preview.png 为预览图片,体积小,很容易加载,真正的图片放在’data-realsrc‘里,当图片漏出屏幕,把’data-realsrc‘给img的src

6》缓存DOM查询:
在这里插入图片描述
7》多个DOM操作一起插入到DOM结构:
在这里插入图片描述

8》尽早开始JS执行:
在这里插入图片描述
选择 DOMContentLoaded,图片视频没加载完不用管

三.优化方案之防抖节流:
1》防抖(debounce):

①.什么是防抖:
在这里插入图片描述
②.例子:

const input1 = document.getElementById('input1')

 let timer = null
 input1.addEventListener('keyup', function () {
     if (timer) {
         clearTimeout(timer)
     }
     timer = setTimeout(() => {
         // 模拟触发 change 事件
        console.log(input1.value)

         // 清空定时器
         timer = null
     }, 500)
 })

比如当我们再输入框连续输入123之后**间隔500ms才会打印input1.value即123,上述代码运用了什么逻辑呢?我们分析一下:

当我们输入1之后,触发了keyup事件,由于timer还是null,if(timer)这段代码略过,给timer赋予一个定时器setTimeout,注意timer此时就有值了,不是null,但是间隔500ms才会触发定时器,因为我们是连续输入的,在触发定时器之前,我们就输入了2,此时回过头来再次触发keyup事件,由于timer已经有值了,执行if(timer)这段代码,会clear清除上次1的定时器,然后继续执行代码,再赋予time一个定时器setTimeout,timer再次有值,之后同理。。。,当我们连续输入最后一个数3后,间隔500ms后,触发定时器,控制台输出input1.value,timer赋值为null,清空定时器。整个过程结束。

③.对上述例子进行封装:

const input1 = document.getElementById('input1');
function debounce(fn, delay = 500) {
    // timer 是闭包中的,不会被外部轻易拿到
    let timer = null

    return function () {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            fn.apply(this, arguments)
            //fn.apply(this, arguments)
            //来保证传进有参函数也可以执行并得到结果
            timer = null
        }, delay)
    }
}

input1.addEventListener('keyup', debounce(function (e) {
    console.log(e.target)
    console.log(input1.value)
}, 600))

--------------------------------------------------------------------------------------------
fn.apply(this, arguments)的意义:如果不这么写,直接fn()的话,会报错,输出的e会 undefined,为什么呢?

下面的这段代码,属于正常的触发input的keyup事件写法,addEventListener第二个参数,回调函数的event即小e指向function

input1.addEventListener('keyup', function(event) {
})

但是在节流(防抖)中,

input1.addEventListener('keyup', debounce(function (e) {
})

debounce()就等于上面代码的 function(),即此段代码的addEventListener第二个参数,回调函数的event即小e指向的是debounce的返回值的返回函数
在这里插入图片描述
而不是

input1.addEventListener('keyup', debounce(function (e) {
})

debounce函数里面的function函数,所以需要
fn.apply(this, arguments)传递参数,从而能输出e.target

--------------------------------------------------------------------------------------------

2》节流(throttle):
①.什么是节流:
在这里插入图片描述
②.例子:
在这里插入图片描述

const div1 = document.getElementById('div1')

 let timer = null
 div1.addEventListener('drag', function (e) {
     if (timer) {
         return
     }
     timer = setTimeout(() => {
         console.log(e.offsetX, e.offsetY)

         timer = null
     }, 100)
 })

上述代码,连续拖拽盒子时,每隔100ms控制台就会输出当前盒子的位置
我们发现节流和防抖其实差不多,就是没有清楚定时器,我们分析一下节流逻辑:
当我们进行拖拽时,触发drag事件,timer为null,不会触发if (timer) 代码,然后timer赋值 setTimeout,100ms后触发此定时器,由于我们不停地拖拽,在触发此定时器之前,我们再次触发drag事件,time有值,触发if (timer) 代码,但是只是单单return,并没有清楚上次定时器的代码,可能此时100ms已经到了,触发上次的定时器,控制台打印结果,然后timer=null,下次拖拽,再次触发drag事件,然后重新建立一个定时器,以此类推,也就是说,每隔100ms触发一次定时器,触发完定时器,在下次拖拽时,马上又建立一个新的定时器,等待100ms后再次触发。

③.对上述例子进行封装:

const div1 = document.getElementById('div1');
function throttle(fn, delay = 100) {
    let timer = null

    return function () {
        if (timer) {
            return
        }
        timer = setTimeout(() => {
            fn.apply(this, arguments)
            timer = null
        }, delay)
    }
}

div1.addEventListener('drag', throttle(function (e) {
    console.log(e.offsetX, e.offsetY)
}))

div1.addEventListener('drag', function(event) {

})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值