前言
我觉得前端性能优化是前端工程化的一部分,做前端性能优化有很多可以做的地方,我在很久之前写过一些文章,可以在博客搜索优化,查看相关文章。其实很多性能优化的地方都要把我一个最佳的度。今天主要写一下vue及webpack在项目中的一些优化。
vue项目中的性能优化
其实vue的性能本身就是很good了,要说再进一步优化,可能有一下几个注意点,仅仅是注意点哦!
1、不要在模板里面写过多表达式
如下:
v-if="isShow && isAdmin && (a || b) "
{{haorooms?haorooms:(resource?resource:"haoroomsresource")}}
类似上面这样的表达式,可以是可以,但是过多,就要通过其他方式,例如可以通过methods 或computed 封装方法。用方法的好处是方便我们在多处判断相同的表达式,其他权限相同的元素再判断展示的时候调用同一个方法即可。
2、循环调用子组件时添加 key
这一点相信很多人都能做的到,用vscode开发的时候,假如不加key,编辑器也会出现警告!循环key最好如下: (item, index) in arr,然后 :key="index",假如数组数据是这样的 ['a' , 'b', 'c', 'a'],使用 :key="item" 显然没有意义。
3、v-show,v-if 的使用
频繁切换的使用 v-show,不频繁切换的使用 v-if。
注意:v-if一个组件,可以让组件重新渲染,通过v-if,我们可以让组件按照一定执行循序执行。
4、尽量不使用 float 布局
尽量少用float,可以用flex或者grid布局。
5、Object.freeze()去除Observer
长久不变的大数据,可以用Object.freeze()去除Observer监听。使用了Object.freeze()这个方法,更改数据,视图也是会变的。例如如下:
export default {
name: 'haorooms test',
data () {
return {
list: Object.freeze([
{ value: 1 },
{ value: 2 }
])
}
},
created(){
this.list[0].value = 100;
console.log(this.list);
this.list=[];
console.log(this.list);
}
}
如上图输出,Object.freeze可以取消监听,但是还是可以改变数值改变dom的。
给list重新赋值之后,又恢复了监听。
6、慎用deep watch
数量量大,开启deep监听的话,很可能造成更大的开销。
7、vue-router
路由优化,可以看路由懒加载
或者如下:
const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'haorooms-foo')
const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'haorooms-foo')
const Baz = r => require.ensure([], () => r(require('./Baz.vue')), 'haorooms-foo')
8、减少不必要的依赖包
例如有些项目用到了图表(echarts),可以选择加载依赖包,不用加载整个echarts库。
9、按需加载
可以用require或者import()按需加载你需要的组件,关于require和import,请看:http://www.haorooms.com/post/vue_project_cg 最后的动态加载依赖项。
10、vue中使用keep-alive
vue2.0提供了一个keep-alive组件,用来缓存组件,避免多次加载相应的组件,减少性能消耗
<keep-alive>
<component>
<!-- 组件将被缓存 -->
</component>
</keep-alive>
使用router. meta属性
// 这是目前用的比较多的方式
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
router设置
...
routes: [
{ path: '/', redirect: '/index', component: Index, meta: { keepAlive: true }},
{
path: '/common',
component: TestParent,
children: [
{ path: '/test2', component: Test2, meta: { keepAlive: true } }
]
}
....
// 表示index和test2都使用keep-alive
keep-alive是一把双刃剑,确实需要缓存组件的时候才使用!
11、善于运用事件代理
我们用 v-for 渲染大量的同样的 DOM 结构时,每个上面都加一个点击事件,这样不是很好,可以考虑通过 HTML5 的 data 的自定义属性做事件代理。,方式如下:
<template>
<div @click="clickfn">
<component v-for="(item,index) in 1000" :key="index" data-click="clickName"></component>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
clickfn(e) {
if(e.target.dataset.click == 'clickName') {
console.log('通过事件委托拿到了自定义属性,这里可以写事件了!')
}
}
}
}
</script>
注:具体情况具体分析,假如click事件要传递参数等,这种方式可能不是很适合了!
webpack相关
webpack功能太强大的,关于跨域,webpack提供了http-proxy-middleware。webpack也提供了css打包去重的一些方法:optimize-css-assets-webpack-plugin
如何减少webpack打包体积,加快webpack的打包速度呢?
解决方法很简单,打包 vender 时不打包 vue、vuex、vue-router、axios 等,换用国内的 bootcdn 直接引入到根目录的 index.html 中。
例如:
<script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
在 webpack 里有个 externals,可以忽略不需要打包的库
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios'
}
此时的 vender 包会非常小,如果不够小还可以拆分其他的库,此时虽然增加了请求的数量,但是远比原来的快了很多!