Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM;但 Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题,所以我们仍然需要去关注 Vue 项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。

代码层面的优化

在vue中,有很多的功能相似,有略微区别的代码,正确的在使用场景下使用适合它的元素,会让代码运行的更加丝滑

1.1 v-if和v-show使用场景

v-if真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show 就简单得多, 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。

所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

比如,你的电脑

v-if就等于是你完全的将他关闭了,需要用时,再将他打开

v-show相当于是睡眠模式,他始终都开着,只是你看不到


1.2 computed和watch使用场景

computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

简单来说就是,对计算结果会进行缓存,如果原始数据不改变,不需要重新计算,直接从缓存中读取结果

但是,方法必须有返回值,减少计算量,牺牲空间,来换取时间,对一些复杂的运算,使用计算属性会非常的有效率

假如,你经常的在一家商店购买十箱苹果, 在普通的函数计算中,需要每次取出苹果价格和数量,在计算属性中,只要你价格和数量没变化,就不需要计算,只需要从缓存中取值就好了

watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

监听属性简单来说就是数据一旦发生改变,会自动触发执行,watch属性中的对应的函数

如果函数中,有两个参数 a和b,a就是修改之后的新值,b是修改之前的旧值

当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。


1.3 v-for遍历必须为item添加key,且避免同时使用v-if

  • 在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue内部机制精准找到该条列表数据。当 状态更新时,新的状态值和旧的状态值对比,较快地定位到这个循环 。

  • 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
        {)
      {
    {
    
    // 不推荐
    <ul>
      <li
        v-for="user in users"
        v-if="user.isActive"
        :key="user.id">
        {{ user.name {{
      </li>
    </ul>

1.4 长列表性能的优化

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);
  {
{;

1.5 事件的销毁

Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。 如果在 js 内使用 addEventListene 等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露

created() {
  addEventListener('click', this.click, false)
{,
beforeDestroy() {
  removeEventListener('click', this.click, false)
{

1.6 图片懒加载

对于图片过多的页面,为了加速页面的加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载,等到滚动到可视区域再去加载,这样对于页面加载性能上会有很大的提升,也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件

  1. 安装插件

    npm install vue-lazyload --save-dev
  2. 在入口文件main.js中引入并使用

    import VueLazyload from 'vue-lazyload'
  3. 在vue中直接使用

    Vue.use(VueLazyload)

    或者添加自定义选项

    Vue.use(VueLazyload, {
    preLoad: 1.3,
    error: 'dist/error.png',
    loading: 'dist/loading.gif',
    attempt: 1
    {)
  4. 在 vue 文件中将 img 标签的 :src 属性直接改为 v-lazy ,从而将图片显示方式更改为懒加载显示

    <img v-lazy="/static/img/1.png">

1.7 提取公共代码

一个项目,不可能只有一个页面,而多个页面中,有相同资源的,重复加载会浪费用户的流量和服务器的成本,每个页面的加载资源太大,导致网页加载缓慢,影响用户体验

所以,我们需要提取公共的代码,抽离成单独的文件,以组件的方式在页面中灵活运用,组件间的应用,请参考这里