本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、基础优化(代码以及编码规范)
1、v-if 和 v-show 区分使用场景
v-if=false时不渲染DOM,v-show会预渲染DOM,v-if 在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建
2、computed 和 watch 区分使用场景
computed:是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch:更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
3、v-for 遍历必须为 item 添加 key,且避免同时使用 v-if 在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。
v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。
4、事件及销毁 Vue组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。 也就是说,在js内使用addEventListener等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露
created() {
addEventListener('touchmove', this.touchmove, false)
},
beforeDestroy() {
removeEventListener('touchmove', this.touchmove, false)
}
5、长列表以及不需要数据劫持的场景 Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze() (冻结) 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。或者可以用 Object.seal() (密封)
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
}
二、网络相关
1、CDN加速 大幅减少生产环境体积; CDN网络将用户请求重定向到就近服务节点; 因为CDN是另一个域名,可以单启一个TCP不占用服务器压力; 可以减少多余cookie发送; 在index.html中引入cdn资源
...
<body>
<div id="app">
</div>
<!-- built files will be auto injected -->
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
<script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script>
</body>
...
修改 build/webpack base.conf.js
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
externals:{
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex':'Vuex',
'vue-resource': 'VueResource'
},
...
}
修改src/main.js src/router/index.js 注释掉import引入的vue,vue-resource
// import Vue from 'vue'
// import VueResource from 'vue-resource'
// Vue.use(VueResource)
2、合理缓存 将长时间不改变的第三方库或者静态资源设置强缓存,max-age; 其他静态资源设置协商缓存;
为了提高用户加载页面的速度,对静态资源进行缓存是非常必要的,根据是否需要重新向服务器发起请求来分类,将 HTTP 缓存规则分为两大类(强制缓存,对比缓存),如果对缓存机制还不是了解很清楚的,可以参考作者写的关于 HTTP 缓存的文章《彻底弄懂HTTP缓存机制及原理》,这里不再赘述。
3、预处理 对于现代浏览器来说,可以给link标签添加preload,prefetch,dns-prefetch属性
preload:预加载相关资源,preload的资源会和页面需要的静态资源并行加载 prefetch:空闲加载,其他资源加载完空间时间加载; dns-prefetch:让浏览器提前对域名进行解析,减少DNS查找的开销,如果你的静态资源和后端接口不是同一个服务器的话,可以将考虑你后端的域名放入link标签加入dns-prefetch属性
4、HTTP2 如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同一域名的tcp连接数量是有限制的(chrome为6个)超过规定数量的tcp连接,则必须要等到之前的请求收到响应后才能继续发送,而http2则可以在一个tcp连接中并发多个请求没有限制,在一些网络较差的环境开启http2性能提升尤为明显
这里极力推荐在支持https协议的服务器中使用http2协议,可以通过web服务器Nginx配置,或是直接让服务器支持http2
nginx开启http2非常简单,在nginx.conf中只需在原来监听的端口后面加上http2就可以了,前提是你的nginx版本不能低于1.95,并且已经开启了https