常见前端性能优化

250 阅读6分钟

前言 

**想要成为一名合格的前端开发工程师,必须要掌握前端性能优化,本文将为大家介绍一些常见的前端性能优化问题,如有遗漏,欢迎补充~**

一、图片优化

1.雪碧图(图片精灵)

图像精灵

是放入

一张单独的图片

中的一系列图像。包含大量图像的网页需要更长时间来下载,同时会生成多个服务器请求。使用图像精灵将

减少

服务器请求数量并

节约带宽


具体操作可以去W3C里面查看教程:www.w3school.com.cn/css/css_ima…

2.图片压缩

要无损压缩!!!
  • 优先使用

    **png**

    而不是

    **GIF**
  • 压缩

    **png**

    /

    **gif动画**

    / 动态生成的图像

  • 使用

    **CSS sprites**

    /

    **png8**
  • 避免使用AlphaImageLoader(用来解决IE6不支持png图片透明度的问题)

  • 去除

    **JPEG**

    的metadata

3.字体图标代替图片

  • SVG

    **SVG**(
    Scalable Vector Graphics

    是一种图像文件格式,意思为可缩放的

    矢量图形

    ,是一种用XML定义的语言,用来描述二维矢量及矢量/栅格图形。优势在于:可以

    任意放大图形显示

    ,但绝不会以牺牲图像质量为代价,平均来讲,SVG文件比JPEGPNG格式的文件要小很多,因此渲染速度也很快。

  • iconfont

    **iconfont**

    是阿里妈妈MUX倾力打造的矢量图标管理、交流平台,设计师将图标上传到Iconfont平台,用户可以

    自定义下载多种格式

    (支持AI/ SVG/ PNG / 代码格式)的icon,平台也可将图标转换为字体,便于前端工程师自由调整与调用。

4.webp图片

  WebP(发音:weppy)是一种同时提供了

有损压缩

无损压缩(可逆压缩)

的图片文件格式,

派生自影像编码格式VP8

。根据Google较早的测试,WebP的无损压缩比网络上找到的PNG档少了45%的文件大小,即使这些PNG档在使用pngcrushPNGOUT处理过,WebP还是

可以 **减少28%** 的文件大小。

二、DOM优化

1.缓存DOM节点查找的结果

  在

同一个节点无需多次查询

的情况下,可以缓存DOM。

var div = document.getElementById('div');

2.防抖和节流

  • 防抖
    所谓防抖,就是指触发事件后在

    n 秒内

    函数

    只能执行一次

    ,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

    //以鼠标滚轮事件为例 function debounce(fn,delay){ //fn为真正执行的函数,delay为间隔时间 var timerId = null; return function(){ var arg = arguments[0]; //访问调用方法的第1个参数 if(timerId){ clearTimeout(timerId); //清除定时器 } timerId = setTimeout(function(){ //设置定时器 fn(arg); },delay) } }

    function move(ev){ //测试上述代码 if(ev.wheelDeltaY > 0){ console.log('向上'); }else{ console.log('向下'); } } document.onwheel = debounce(move,2000); //每隔两秒执行一次

  • 节流
    所谓节流,就是指

    连续触发事件

    但是在 n 秒中

    只执行一次函数

    。节流会稀释函数的执行频率,单位时间内, 只会触发一次事件,如果事件触发后,又重复触发了同一事件,则忽略后面触发的事件,直到第一次事件的计时结束。

    //以鼠标滚轮事件为例 function throttle(fn,delay){ var timerId = null; return function(){ var that = this; var arg = arguments[0]; //访问调用方法的第1个参数 if(timerId) return; timerId = setTimeout(function(){ //设置定时器 fn(arg,that); timerId = null; },delay) } }

    function move(ev,obj){ //测试上述代码 console.log(obj); if(ev.wheelDeltaY > 0){ console.log('向上'); }else{ console.log('向下'); } } document.onwheel = throttle(move,1000);

3.事件代理

  指将事件监听器注册在父级元素上,把

原本需要绑定在子元素

的响应事件(clickkeydown等)

委托给父元素

,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。

简单来说,比如你们宿舍的人都要取快递,一种方法是你们一个个去取各自的快递;还有一种方法是把所有要取的快递委托给某一个人,当他把所有快递取回来后,再根据收件人信息分发给每一个人。这个被委托的人就相当于父元素。

  • addEventListener( )
    1)

    语法

    element.addEventListener(event, function, useCapture)
    2)

    参数值
    参数描述event必须。字符串,指定事件名。注意:不要使用"on”前缀(例如使用“click”,而不是“onclick”)function必须。指定事件触发时要执行的函数。当事件对象会作为第一个参数传入函数。useCapture可选。布尔值,指定事件是否在捕获或冒泡阶段执行。
    

3)移出事件监听:element.removeEventListener(event, function,useCapture)

4.减少合并DOM操作

  • 在内存中操作DOM
    使用createDocumentFragment()方法创建虚拟的节点对象,让DOM操作发生在

    内存中

    ,而不是页面上。

    语法

    document.createDocumentFragment()

  • 批量操作DOM
    由于DOM操作可能会造成浏览器回流,所以要

    避免频繁操作DOM

    。可以使用innerHTML属性批量生成DOM节点,具体操作为

    字符串拼接

    ,再用innerHTML更新DOM。
    不过如果代码比较多的情况下,手动拼接就比较麻烦。(因为编辑器里不会有提示~~)

    发送

    var pNode = document.getElementById('p'); //获取p标签节点 var msg = document.getElementById('msg'); //获取节点的文字内容 function sendMsg(){ var val = msg.value; //存放文字内容 p.innerHTML += <p>${val}</p> //字符串拼接 }

  • 批量操作CSS样式
    1)

    切换class
    #tab{ width: 600px; height: 300px; margin: 50px auto; border: 1px solid #000; } #tab ul{ display: flex; justify-content: space-between; } #tab li{ height: 30px; line-height: 30px; padding: 0 10px; flex-grow: 1; background: #f1f1f1; transition: 0.3s; } #tab li.current{ background: deeppink; } .tabItem{ display: none; } .tabItem.current{ display: block; }
    • 电影
    • 电视
    • 动漫
    • 新闻
    THIS IS TAB 1
    THIS IS TAB 2
    THIS IS TAB 3
    THIS IS TAB 4

    //jQuery代码 ('#tab li').on('click',function(){ var index=(this).index()//返回元素的索引 (this).add((this).add(('.tabItem').eq(index)).addClass('current').siblings().removeClass('current') })

5.DOM读写分离

  浏览器具有

惰性渲染机制

,连接多次修改DOM可能只触发浏览器的一次渲染。而如果修改DOM后,立即读取DOM,为了保证

读取到正确的**DOM值**

,会触发浏览器的一次渲染。因此,

修改DOM

的操作要与

访问DOM
分开进行

6.DOM元素离线更新

  当对DOM节点进行较大的改变时,需要先将元素脱离文档流,然后进行改变操作,最后再放回到文档流中。例如appendChild等都可以使用

Document Fragment对象

进行离线操作,带元素“组装”完成后再一次插入页面,或者使用 display:none 对元素隐藏,在元素“消失”后进行相关操作。

<ul id='list'></ul>

var ul = document.getElementById('list')
ul.style.display = 'none';  //脱离文档流
// 对ul进行相关操作
ul.style.display = 'block';  //放回文档流