前端如果不懂性能优化,那和咸鱼有什么区别

前端性能优化

优化的分类:

  • 网页初始过程中的优化。即用户输入域名/ip按下请求按钮,到最终网页可以使用的过程。
  • 用户交互过程的优化。即用户完全加载后,用户进行操作交互的过程。

优化着手点:

  • 网络资源请求和加载类,js、css、图片资源等请求过程的优化。
  • 网页渲染
  • js脚本

网络资源请求的优化

css和js资源的优化
  • 内联
    • 优点:减少http请求
    • 缺点:
      • 没办法复用
      • 似的HTML文件变大,加载时间边长
      • 都写在HTML中,不利于后期维护(目前是有手段可以在开发阶段进行外部引入,然后在代码上线时候解析成内联样式)
  • 外部引入
    • 优缺点和内联相反

优化方式:

  1. 到底使用内联还是外部引入?
    • 最好两者相结合
    • 首屏急需的css和js内联进来
    • 其他屏幕的可以使用外部引入方式
  2. 引用css和js的时机
    • css越早引用越好:
      • css放在header里
      • 如果是最后引用,用户可能会看到无样式的html结构,影响体验
    • js一般越晚引用越好,有时候也需要在一开始引用(header中)
      • js放在body中,dom元素之后
      • 如果是最早引用,js无法操控dom,或者js脚本执行太慢会影响dom的加载,用户会有可能体验到短暂的白屏
      • 一般是越往后越好,但是像一些屏幕适配,ajax请求数据之类和操作dom无关的,可以放在前边(header中)
  3. 避免重复的资源请求
  4. 减小http请求资源的大小,用工具将css、js代码混淆,大小压缩,去除掉注释、空格、换行等生产无关的代码
  5. 减少http请求次数,合并请求资源数量,比如css、js合并,可以使用工具进行多个js或css合并,网上都有这些工具
  6. http缓存,一般是服务端设置
图片资源和其他的优化

着手点:

  1. 解决图片大的优化手段
  2. 解决图片多的优化手段

解决图片大的手段:

  1. 图片压缩处理,利用工具
  2. 使用更高压缩比格式的图片格式,例如webp
  3. 尽量少用图片:
    • 使用图标字体带胎图片
    • 利用css画图

解决图片多的手段:

  1. 合理使用base64内嵌图片,即转换成二进制图片
  2. 合并静态资源图片
    • 雪碧图,比如有个导航图片很多个,可以将这些图片合并成一个很长的图片,然后用css的position和background进行选择使用

其他优化:

  1. 避免dom树套太多层级

  2. 避免空链接,类似这样:

    	// 不要这样写:
        <a href="">aaa</a>
        // 也不要这样写:
        <a href="###">aaa</a>
    
        // 而是要这样写:
        <a href="javascript:;">aaa</a>
        <img scr="img/blank.jpg" alt="">
    
    
  3. 避免使用慢元素:table和iframe

    • table:table会把下面的tr和td读取完毕之后再渲染,而不是一行一行地渲染,所以避免使用,可以使用ul+li进行模拟
    • iframe:会先读取iframe里面的所有元素之后,再加载iframe,所以也避免使用
  4. 主要内容写前边,次要内容写后边

    • 网页加载是根据html资源从上往下加载的
    • 例如网商页面,主要内容是商品区域,次要内容是导航栏和其他
    • 这个时候就可以把商品区域的dom写在前边,导航栏和其他的结构写在后边

CSS选择器的优化

方法:

  1. 选择时候不要有无所谓的或者额外的修饰

  2. 尽量不要用ID进行选择,虽然ID选择速度比class快,但是不利于复用(此条不属于优化相关)

  3. 尽量保持层级简单,不要套用太多复杂的层级结构,而且class命名空间也一定要体验层级结构和业务归属,例如demo-container-content就可以一眼看出是demo标签下的东西,层级较少时候也容易定位不会产生误选,另外css层级解析是从右往左解析,而不是从左往右:

    // 分析:例如下方代码:css会先查找demo-container-content,然后向上一层查找demo-container,最后向上一层查找demo,如果三个都满足了,才会定位到这个元素
    
    // html
    <div class="demo">
       <div class="demo-container">
           <div class="demo-container-content"></div>
       </div>
    </div>
    
    // css
    .demo .demo-container .demo-container-content{
       width: 20px;
    }
    
  4. 避免使用通配符*

  5. 删除掉空属性的选择器

  6. 避免使用正则选择器

  7. 提取公共部分尽量合并css选择器,减少css文件大小

  8. 合并属性,例如margin的四个属性合并,还是为了减少css文件大小

  9. 使用动画时候优先使用css3

  10. 尽量使用flex布局而不是float布局,float布局在移动端比较耗费性能

DOM操作优化

着手点:

  1. 加快dom操作的速度
  2. 减少dom操作的次数

优化方法:

  1. 尽量用id获取元素,id比class选择效率高
  2. 尽量从目标元素的父元素获取,什么意思呢,就是如果已经获取了目标元素的父元素,那么就不要再从document.getElement这里写了,而是写parentNode.getElement
  3. 尽量要使用变量缓存下来:如果多次进行相同节点的dom操作,就用变量缓存下来,对变量进行操作,减少dom获取次数
  4. 尽量不要再循环中进行dom操作,而是可以使用dom碎片临时变量存下来,然后循环后统一操作:document.createDocumentFragment()
  5. 不要再循环中重复创建相同的node元素节点,即不要再循环中使用document.createElement,而是要在循环之前创建,然后在循环之中进行clone:ele.cloneNode(true)(true表示clone元素内容,false为不克隆,一定要指定,因为各个浏览器的默认参数不一样)
  6. 循环头中不要每次都引入element.length,这样也是会读取dom的,而是可以使用变量缓存下来:for(var i=0, num = element.length; i< num; i++){}
  7. 修改样式时候尽量通过动态增删class,然后用css进行样式修改,尽量不用js修改style属性,因为js修改style会导致DOM渲染重排,重排成本高于重绘

DOM渲染:

  • 重排:dom结构发生改变
  • 重绘:节点样式改变
  • 重绘成本低于重排

事件优化

事件委托:
  • 使用原因:例如跑马灯里切换用的小圆点,如果每一个循环添加listener,就会降低js执行效率
  • 做法:在他们的父容器中统一加入listener,只需要绑定一次,然后用冒泡方式获取点击,并且通过判断回调的event,进行相关判断
	// 方法一:原生js 
	parent.addEventListener('click', function(ev){
    	if(根据ev判断是否点到了想要的元素){
        	执行相关代码
        }
    }, false)

    // 方法二:jQuery/zepto库
    $(parent).on('click', 'class或者其他选择器,或者其他判断条件', function(){
    	执行相关代码
    })
事件节流/事件稀释:
  • 使用原因:类似scroll、resize、touchmove、mousemove等瞬间会触发很多遍的回调操作,回调代码复杂的话会体验到十分明显的卡顿
  • 做法:使用setTimeout进行节流,减少触发次数
	var timer = null;
    window.addEventListener('scroll', function(){
    	clearTimeout(timer);
        timer = setTimeout(function(){
        	console.log('回调')
        }, 20)
    }, false)

资源按需加载(懒加载/延迟加载)、预加载

懒加载
  • 当模块出现在屏幕的时候再加载
  • 怎么判断是否出现在屏幕呢?可以使用元素的getBoundingClientRect()方法判断,getBoundingClientRect()方法说明:
    • 方法会返回top、bottom、left、right四个值
    • top:元素上边距到屏幕顶部的像素,在屏幕顶部上方时候为负,在屏幕顶部下方时候为正
    • bottom:元素下边距到屏幕顶部的像素,在屏幕顶部上方时候为负,在屏幕顶部下方时候为正
    • left:元素左边距到屏幕最左的像素,在屏幕最左的左边时候为负,在屏幕最左的右边为正
    • right:元素右边距到屏幕最左的像素,在屏幕最左的左边时候为负,在屏幕最左的右边为正
  • 那么判断是否出现在屏幕中就可以使用以下方法:
    	function isInScreen(el){
        	return el.bottom > 0 && el.top < window.innerHeight && el.left < window.innerWidth && el.right > 0;
        }
    
    

以懒加载图片为例,写一下最后懒加载的代码:

	// 前提:先在图片img标签上定义class="lazyload-img-tag",并且图片所需要的真实src放在自定义属性:`data-src="xxx.jpg"`,真实的src可以先用loading图片占位

    // 根据className得到所有需要懒加载的图片,这个是把伪数组转换为真数组,至于call和原型链之类的,以后再细说了
	var imgArr = Array.prototype.slice.call(document.querySelectorAll(".lazyload-img-tag"));

    lazyLoad();// 先加载首屏

    // 滚动时候动态加载,可以考虑使用事件节流
    window.addEventListener('scroll', function(){
    	lazyLoad();
    }, false)

	// 懒加载
    function lazyLoad(){
    	for(var i = 0;i < imgArr.length; i++){
        	// 如果在屏幕范围内,就加载
        	if(isInScreen(imgArr[i])){
            	// 用先定义好的data-src属性中的地址替换上真实的src
            	imgArr[i].src = imgArr[i].getAttribute('data-src');
                // 从数组中删掉,以后不用再加载一遍
                imgArr.splice(i,1);
                // 因为删掉了一个元素,i++已经执行,所以数组下标要减一,保证可以数组可以循环而且无遗漏
            	i = i - 1;
            }
        }
    }

    function isInScreen(el){
        return el.bottom > 0 && el.top < window.innerHeight && el.left < window.innerWidth && el.right > 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值