前端面试之 性能优化 篇

167 阅读8分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情

如何进行前端性能优化?(必会)

  1. 减少 http 请求

    减少 http 请求的方案主要有:合并 JavaScript 和 CSS 文件、合并图片 CSS Sprites、图像映射(Image Map)和使用 Data URI 来编码图片,图片较多的页面也可以使用 lazyLoad 等技术进行优化。

  2. 减少对 DOM 的操作

    修改和访问 DOM 元素会造成页面的 Repaint(重绘)和 Reflow(重排),循环对 DOM 操作更是不推荐的行为。所以合理的使用 JavaScript 变量储存内容,考虑大量 DOM 元素中循环的性能开销,在循环结束时一次性写入。

    减少对 DOM 元素的查询和修改,查询时可将其赋值给局部变量。

    注:在 IE 中:hover 会降低响应速度。

  3. 使用 JSON 格式来进行数据交换

    JSON 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。同时,JSON 是 JavaScript 原生格式,这意味着在 javaScript 中处理 JSON 数据不需要任何特殊的API 或工具包。与 XML 序列化相比,JSON 序列化后产生的数据一般要比 XML 序列化后数据体

    积小

  4. 高效使用 HTML 标签和 CSS 样式

    HTML 是一门标记语言,使用合理的 HTML 标签前你必须了解其属性,比如 Flow Elements,Metadata Elements ,Phrasing Elements。比较基础的就是要知道块级元素和内联元素、盒模型、SEO 方面的知识。

    CSS 是用来渲染页面的,也是存在渲染效率的问题。CSS 选择符是从右向左进行匹配的,当页面被触发引起回流(reflow)的时候,低效的选择符依然会引发更高的开销,所以要避免低效。

  5. 使用 CDN 加速(内容分发网络)

    其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN 系统能够实时的根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上

  6. 将 CSS 和 JS 放到外部文件中引用,CSS 放头,JS 放尾

  7. 精简 CSS 和 JS 文件

  8. 压缩图片和使用图片 Sprite 技术

  9. 注意控制 Cookie 大小和污染

    因为 Cookie 是本地的磁盘文件,每次浏览器都会去读取相应的 Cookie,所以建议去除不必要的Coockie,使 Coockie 体积尽量小以减少对用户响应的影响;

    使用 Cookie 跨域操作时注意在适应级别的域名上设置 Coockie 以便使子域名不受其影响

    Coockie 是有生命周期的,所以请注意设置合理的过期时间,合理地 Expire 时间和不要过早去清除 Coockie,都会改善用户的响应时间。

一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。(必会)

图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。

如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。

如果图片为 css 图片,可以使用 CSSsprite,SVGsprite,Iconfont、Base64 等技术。

如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。

如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。

兼容问题(必会)

  1. 图片加 a 标签在 IE9 中会有边框(必会)

    解决方案:img{border:none;}

  2. rgba 不支持 IE8(必会)

    解决方案:可以用 opacity

    eg:opacity:0.7;/FF chrome safari opera/

    filter:alpha(opacity:70);/用了 ie 滤镜,可以兼容 ie/

    但是,需要注意的是,opacity 会影响里面元素的透明度

  3. display:inline-blockie6/7 不支持(必会)

    解决方案:Display:inline-block;Display:inline;

  4. 不同浏览器的标签默认的外补丁和内补丁不同(必会)

    问题:随便写几个标签,不加样式控制的情况下,各自的 margin 和 padding 差异较大。

    解决方案:CSS 里*{margin:0;padding:0;}

  5. 块属性标签 float 后,又有横行的 margin 情况下,在 IE6 显示 margin比设置的大(必会)

    问题:IE6 中后面的一块被顶到下一行

    解决方案:在 float 的标签样式控制中加入 display:inline;将其转化为行内属性

  6. 设置较小高度标签(一般小于 10px),在 IE6,IE7 中高度超出自己设置高度(必会)

    问题:IE6、7 里这个标签的高度不受控制,超出自己设置的高度

    解决方案:给超出高度的标签设置 overflow:hidden;或者设置行高 line-height 小于你设置的高度。

    注:这种情况一般出现在我们设置小圆角背景的标签里。出现这个问题的原因是 IE8 之前的浏览器都会给标签一个最小默认的行高的高度。即使你的标签是空的,这个标签的高度还是会达到默认的行高。

  7. IE9 一下浏览器不能使用 opacity(必会)

    解决方案:

    opacity: 0.5;
    filter: alpha(opacity = 50);
    filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);
    
  8. IE6 背景闪烁的问题(必会)

    问题:链接、按钮用 CSSsprites 作为背景,在 ie6 下会有背景图闪烁的现象。原因是 IE6 没有将背景图缓存,每次触发 hover 的时候都会重新加载

    解决:可以用 JavaScript 设置 ie6 缓存这些图片:

    document.execCommand("BackgroundImageCache", false, true);

  9. event 事件问题:(必会)

    //event 事件问题
    document.onclick=function(ev){//谷歌火狐的写法,IE9 以上支持,往下不支持;
    	var e=ev; console.log(e);
    }
    document.onclick=function(){//谷歌和 IE 支持,火狐不支持;
    	var e=event; console.log(e); 
    }
    document.onclick=function(ev){//兼容写法;
    	var e=ev||window.event; 
    	var mouseX=e.clientX;//鼠标 X 轴的坐标
    	var mouseY=e.clientY;//鼠标 Y 轴的坐标
    }
    
  10. DOM 节点相关的问题(必会)

    //DOM 节点相关,主要兼容 IE 6 7 8
    function nextnode(obj){//获取下一个兄弟节点
    	if (obj.nextElementSibling) {
    		return obj.nextElementSibling; 
    	} else{
    		return obj.nextSibling; 
    	}; 
    }
    function prenode(obj){//获取上一个兄弟节点
    	if (obj.previousElementSibling) {
    		return obj.previousElementSibling; 
    	} else{
    		return obj.previousSibling; 
    	}; 
    }
    function firstnode(obj){//获取第一个子节点
    	if (obj.firstElementChild) {
    		return obj.firstElementChild;//非 IE678 支持
    	} else{
    		return obj.firstChild;//IE678 支持
    	}; 
    }
    function lastnode(obj){//获取最后一个子节点
    	if (obj.lastElementChild) {
    		return obj.lastElementChild;//非 IE678 支持
    	} else{
    		return obj.lastChild;//IE678 支持
    	}; 
    }
    
  11. 设置监听事件:(必会)

    //设置监听事件
    function addEvent(obj,type,fn){
        //添加事件监听,三个参数分别为 对象、事件类型、事件处理函数,默认为 false
    	if (obj.addEventListener) { 		
            obj.addEventListener(type,fn,false);//非 IE
        } else{ 
            obj.attachEvent('on'+type,fn);//ie,这里已经加上 on,传参的时候注意不要重复加了
        }; 
    }
    function removeEvent(obj,type,fn){//删除事件监听
        if (obj.removeEventListener) { 
            obj.removeEventListener(type,fn,false);//非 IE
        } else{ 
            obj.detachEvent('on'+type,fn);//ie,这里已经加上 on,传参的时候注意不要重复加了
        }; 
    }
    
  12. 阻止事件冒泡:(必会)

    //js 阻止事件冒泡,这里使用 click 事件为例
    document.onclick=function(e){ 
    	var e=e||window.event; 
    	if (e.stopPropagation) { 
    		e.stopPropagation();//W3C 标准
    	}else{ 
    		e.cancelBubble=true;//IE.... 
    	}
    }
    
  13. 阻止默认事件:(必会)

    //js 阻止默认事件
    document.onclick=function(e){ 
    	var e=e||window.event; 
    	if (e.preventDefault) { 
    		e.preventDefault();//W3C 标准
    	}else{ 
    		e.returnValue='false';//IE.. 
    	}
    }
    
  14. IOS 移动端 click 事件 300ms 的延迟响应(必会)

    解决方案:
    fastclick 可以解决在手机上点击事件的 300ms 延迟
    zepto 的 touch 模块,tap 事件也是为了解决在 click 的延迟问题
    触 摸事 件 的响 应顺 序 为 touchstart --> touchmove --> touchend --> click,也 可以 通 过绑 定
    ontouchstart 事件,加快对事件的响应,解决 300ms 延迟问题
    
  15. 一些情况下对非可点击元素如(label,span)监听 click 事件,ios 下不会触发(必会)

    解决方案:css 增加 cursor:pointer。

  16. 三星手机遮罩层下的 input、select、a 等元素可以被点击和 focus(点击穿透) (必会)

    有两种解决方案:

    • 通过层显示以后加入对应的 class 名控制,截断显示层下方可获取焦点元素的事件获取
    • 通过将可获取焦点元素加入的 disabled 属性,也可以利用属性加 dom 锁定的方式(disabled 的一种变换方式)
  17. Input 的 placeholder 会出现文本位置偏上的情况(必会)

    input 的 placeholder 会出现文本位置偏上的情况:PC 端设置 line-height 等于 height 能够对齐,而移动端仍然是偏上,解决是设置 line-height:normal