从三个方面
第一个方面:代码层面的优化
• v-if 和 v-show 区分使用场景
• computed 和 watch 区分使用场景
• v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
• 长列表性能优化
• 事件的销毁
• 图片资源懒加载
• 路由懒加载
• 第三方插件的按需引入
• 优化无限列表性能
• 服务端渲染 SSR or 预渲染
第二个方面:Webpack 层面的优化
• Webpack 对图片进行压缩
• 减少 ES6 转为 ES5 的冗余代码
• 提取公共代码
• 模板预编译
• 提取组件的 CSS
• 优化 SourceMap
• 构建结果输出分析
• Vue 项目的编译优化
第三个方面:基础的 Web 技术的优化
• 开启 gzip 压缩
• 浏览器缓存
• CDN 的使用
• 使用 Chrome Performance 查找性能瓶颈
常用到的几种介绍
v-if 和 v-show 区分使用场景
v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 就简单得多, 不管初始条件是什么,元素总是会被渲染,
并且只是简单地基于 CSS 的 display 属性进行切换。
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;
v-show 则适用于需要非常频繁切换条件的场景。
computed 和 watch 区分使用场景
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,
下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,
每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,
因为可以利用 computed 的缓存特性,
避免每次获取值时,都要重新计算;
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,
使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,
并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
v-for 遍历必须为 item 添加 key
在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,
方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,
新的状态值和旧的状态值对比,较快地定位到 diff 。
v-for 遍历避免同时使用 v-if
v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,
尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。
例子:
<ul>
<li
v-for="user in activeUsers"
:key="user.id">
{{ user.name }}
</li>
</ul>
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
长列表性能优化
Vue 会通过 Object.defineProperty 对数据进行劫持,
来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,
不会有任何改变,我们就不需要 Vue 来劫持我们的数据,
在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,
那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,
一旦被冻结的对象就再也不能被修改了。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
事件的销毁
Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。如果在 js 内使用 addEventListene 等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露,如:
created() {
addEventListener(‘click’, this.click, false)
},
beforeDestroy() {
removeEventListener(‘click’, this.click, false)
}
图片资源懒加载
对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的
图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,
也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件
1
2
3
路由懒加载
Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,
当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,
这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。
第三方插件的按需引入
在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,
我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的
通过CDN引入第三方插件
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>