[TOC]
## 前端性能优化
### `css` 样式优化
* 当一个属性只有一个值需要修改时,尽量只设置这一个属性值
例如:
~~~
// 不推荐使用
background: '#fff'
// 推荐使用
background-color: '#fff'
~~~
* 在设置多个样式时,尽量避免设置行内样式;使用更改 `className` 的方式替换 `style.xxx = xxx`
> why: 每次修改元素的style属性都会触发回流操作,使用className更改可多次创建,一次更改
~~~
// 例如: 在服务的状态发生改变时,我们需要更改相应标签的样式
watch: {
status(newVal) {
switch(newVal) {
case '运行':
this.serviceClass = 'run';
break;
......
}
}
}
~~~
### `DOM` 优化
* 尽量减少 `DOM` 元素数量
~~~
// 查看当前页面dom元素数量
console.log('number of elements', document.getElementsByTagName( '*' ).length)
// 正常页面的 `dom` 元素数量一般不应该超过1000个
~~~
* 优化 `DOM` 交互
对于只会渲染一次的数值,在 `vue` 中应尽量使用 `v-once` 指令
~~~
<p v-once>这个将不会改变: {{ msg }}</p>
~~~
* 区分 `v-show` 与 `v-if` 的使用
> 在隐藏元素时,前者只会设置样式 `display: none` ,后者会移除元素
### `HTML` 优化
* 避免空的 `src` 和 `href`
> 为空时,浏览器渲染时会把当前页面的url作为它们的属性值,从而把页面的内容加载进来作为它们的值
* 合理架构,使DOM结构尽量简单
* 利用 `LocalStorage` 合理缓存资源
### 内存优化
JavaScript存在内存回收机制,可将一些不再使用的变量,方法销毁,释放其占用的内存。在某些情况下,无法被回收(函数执行完毕后,在函数内部所声明的对象不一定会被销毁)
* 变量优化
* 尽量选用局部变量而不是全局变量(回收机制很难判断何时回收全局变量;局部变量访问速度更快)
* 善用回调
除了使用闭包访问内部变量,我们还可使用回调函数处理
优点:回调函数本身通常为临时的匿名函数,被请求执行后,回调函数自身的引用会被解除,同时得到回收。
~~~
const getData = callback => {
const data = "some big data";
callback(data);
}
getData(data => {
console.log("data:", data);
})
~~~
* 对象优化
* 减少不必要的对象创建
复杂的 `javaScript` 对象,其创建时时间和空间的开销都很大,应该尽量考虑创建后进行存储。
### 类型转换
* 将数字转为为字符串
从性能上讲,`"" + 1` 效率最高,`"" + 1` > `String()` > `.toString()` > `new String()`
~~~
// String() 属于内部函数,所以速度很快
// .toString() 需要查询原型中的函数,所以速度略慢
~~~
* 浮点数转换为整数
错误使用 `parseInt()`
~~~
` parseInt 是将字符串转换为数字,而不是浮点数转为整型的方法 `
~~~
应该使用 `Math.floor()` 或者 `Math.round()`
~~~
// Math.floor() 返回小于等于参数的最大整数
Math.floor(5.5) // 5
Math.floor(-1.5) // -2
// Math.round() 四舍五入返回整数
Math.round(5.5) // 6
Math.round(-1.5) // -1
Math.round(-1.6) // -2
~~~
### 逻辑判断优化
* `switch` 语句
在 `if-else` 语句中,当 `else-if` 有至少两个时,转换为 `switch` 语句
> tips: 在case中未写break时会继续向下执行代码, 这在需要判断的选项的值一致时起作用。
~~~
let result = ''
const now = new Date()
const day = now.getDay()
switch(day) {
case 0:
case 6:
result = '休息日'
break
case 1:
result = '周一'
break
// ...
default:
break
}
~~~
### 数组优化
* 初始化数组直接使用 `const arr = [];` ,不要使用 `const arr = new Array();`
* 在遍历数组时,可先保存数组长度到局部变量,避免多次查询数组长度
~~~
const length = arr.length;
for (let i = 0; i < length; i++) {}
~~~
### 动画优化
* 设置动画元素 `display` 为 `absolute` 或 `fixed`
这样做只会触发 `repaint` , 通常情况下会造成频繁的 `reflow`
### 缓存过期设置
* 在使用localStorage、session等缓存技术时,可设置他们的过期时间,以定期清理一些数据。
例如:
~~~
// 以localstorage为例
class LocalStorage {
constructor() {
this.source = window.localStorage;
this.init();
}
init() {
const reg = /__time/;
const data = this.source;
const list = Object.keys(data);
const time = new Date().getTime();
if(list.length > 0){
list.forEach(item => {
if (reg.test(item)) {
if (data[item] < time) {
const k = item.replace(reg, "")
this.remove(k);
this.remove(item);
}
}
})
};
}
save(k, v, needTime = false, endTime = 3 * 1000) {
localStorage.setItem(k, v);
if (needTime) {
const time = new Date().getTime() + endTime;
localStorage.setItem(`${k}__time`, time);
}
}
remove(k) {
localStorage.removeItem(k);
}
}
~~~
## 小结
前端涉及到的性能优化问题,大多是由编码习惯导致的,多注意一些细节上的代码编写,可大幅度的优化性能上的问题。多看一些 “大佬” 的代码,会提高自己代码的编写质量。同时,代码走查也是个不错的方式,自检或协助检查亦可以提高代码编写质量,去除一些不好的书写习惯。