前端性能优化 - 编码优化

216 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

前言:

一味的编码优化,必将导致代码的可阅读性差,所以优化程度自己看着来。

一、减少HTTP请求

合并js、css文件,webpack打包已处理。

二、CSS文件处理

1、CSS文件放顶部

2、避免使用CSS表达式

如:background-color:expression((new Date().getHours()%2?"#B8D4FF":"#F08A00"));

3、尽量避免內联样式

内联样式:使用style属性添加到元素的样式

建议:使用classname代替大量的内联样式,最直接的可以减少代码量。

4、封装公共样式

常用公共样式如下:

// 通过…表示文本未完全显示
<span class="span-ellipsis" slot-scope="{ node, data }"></span>
.span-ellipsis {
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: inline-block;
  // display: block;
}
// 清除浮动
<div class='just-clear-float'></div>
.just-clear-float {
  clear: both;
}
<div class='clearfix'></div>
.clearfix:after {
    display: block;
    content: '';
    clear: both;
    height:0;
}

5、少用ID样式选择器

如果需要,请保证ID的唯一性,且去掉前方嵌套(.content #test)完全是浪费性能。

6、减少使用关系型样式表的写法

直接使用唯一的类名即可最大限度的提升渲染引擎绘制渲染树等效率

改:

.frame-map .top-left {
	……
}

为:

.top-left {
	……
}

注意,需要确保top-left样式类名唯一或样式相同。

7、元素的嵌套层级尽量不超过3层

因为CSS渲染规则:从右到左遍历渲染。

所以正确的使用css前缀,缩短css选择器,多使用伪元素等帮助定位。

对于css中可继承的属性,如font-size,尽量使用继承,少一点设置。

8、CSS的精简

移除空的css,颜色使用缩写,使用0代替0px,合并可以合并的样式,样式最后一行的’;’也是可以省略的。

举例如下:

.right {
    color: #fff;
    padding-top: 0; 
    margin: 0 10px;
    border: 1px solid #111
}

注意:

使用webpack打包完后,它会把0px去掉px,所以这些影响代码可读性的优化可以省省了。

9、尽量使用css动画

动画和过渡能用CSS3解决的,就不要使用JS。

10、对于复杂的元素

设置position为absolute或fixed

三、JS文件处理

1、JS文件放尾部

2、循环语句

总次数使用局部变量:for( var i = 0;i < arr.length;i++)将arr.length定义在外。

循环次数比较多时,尽量用递减代替递增。

3、条件语句

使用switch语句,层数比较深时,性能比if会更好,并将概率大的条件对应的语句放在最上面,这样可以减少判断次数。

JS的switch语句可以比较字符串,且case条件如果其中不定义变量可以省略大括号{}包起来,但是break千万不能省略!最后的default,如果没有可以省略。

4、字符串优化

拼接字符串,"+"号每次运行都会开辟新的内存并生成新的字符串变量,效率低,高效的做法是使用数组的join方法。

但是在字符串拼接量小时,两者差别不大,且用join需要额外转成数组的消耗,所以可以继续使用"+"拼接字符串。

5、定时器优化

定时器方法建议使用顺序:setTimeout、requestAnimationFrame、setInterval

6、精简JS

避免重复脚本,删除console.log语句,移除不必要的空白字符和注释,减少javascript文件的大小。

7、集合优化

ES6新标准将Set集合与Map集合添加到JS中。

Set集合是一种无重复元素的列表,类似数组,但是没有下标,常用于数组去重、查找集合内元素是否存在,效率更高。

Map集合是存放键值对的对象,类似对象类型,对象类型的key只支持字符串,Map更加强大,支持所有数据类型。

8、异步JS资源

官方资料:

www.w3school.com.cn/tags/tag_sc…

  • async 规定异步执行脚本(仅适用于外部脚本)。
  • defer 规定是否对脚本执行进行延迟,直到页面加载为止。

但是浏览器只有IE支持defer属性,有兴趣可以了解一下。

四、DOM相关操作

1、重绘与回流

频繁触发重绘与回流,会导致UI频繁渲染,最终导致js变慢。

回流必将引起重绘,而重绘不一定会引起回流!

  • 回流:元素的规模尺寸、布局、隐藏等改变而需要重新构建render tree。
  • 重绘:元素更新属性,只是影响元素的外观,风格,而不会影响布局的比如background-color。
  • 建议: 用opacity替代visibility(触发重绘)

opacity=0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定一些事件,如click事件,那么点击该区域,也能触发点击事件的。

visibility=hidden,该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件。

display=none,把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删除掉一样。

2、DOM样式修改

不要一条一条地修改DOM的样式,预先定义好class,然后修改DOM的className。

3、DOM离线后修改

先把DOM给display:none(有一次Reflow),然后你修改100次(不会重发任何Reflow),然后再把它显示出来。

4、避免使用空的href、src

当标签的 href 属性为空,或<script>、<img>、<iframe>标签的 src 属性为空时,浏览器在渲染的过程中仍会将 href 属性或 src 属性中的空内容进行加载,直至加载失败。

五、vue相关优化

1、避免重定向

url结尾的斜线不要

2、减少watch的使用

尽量使用原生的@change方法替代watch,但因为需要实时性,写入一个字符就触发,只能用watch不能用change。

3、使用简写

v-on:简写为@,v-bind简写为:

4、Vuex.Store层级不要过多

5、清除定时器等监听事件

记得清除setTimeout、解绑addEventListener监听事件等。在如下两个钩子函数中调用都可以:

beforeDestroy(对象即将被销毁)

实例销毁之前调用。在这一步,实例仍然完全可用。

destroyed(对象已销毁)

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

官方资料:

cn.vuejs.org/v2/api/#%E9…

6、vue-router路由懒加载

详见:前端性能优化-番外篇-动态路由和vue-router懒加载 juejin.cn/editor/draf…

7、Object.freeze

详见:前端性能优化-番外篇-Object.freeze到底用在哪 juejin.cn/editor/draf…