This website requires JavaScript.

记录: Vue 性能优化方法

by  饲养员  

1 - 路由懒加载

const router = new VueRouter({
    routes: [
        {
            path: "/",
            component: () => import('@/views/Home.vue')
        }
    ]
})

日常编写代码工作中也是经常用到的。

2 - ==keep-alive== 缓存页面

相信大家也会经常听到 ==keep-alive== 这个名词,但它到底是什么呢?

事实上,在日常的开发中,很多组件并不需要每次都初始化,所以,为了优化性能,我们希望能将组件进行持久化,维持它的状态,防止每次都重新初始化。

而 keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。

这也就是常说的组件缓存了。

==keep-alive== 使用起来也是非常方便的:

<template>
    <div id="root">
        <keep-alive>
            <router-view />
        </keep-alive>
    </div>
<template/>

keep-alive 可以接受两个参数,方便更加细节的操作:

  • include: 只有匹配的组件会被缓存
  • exclude: 任何匹配的组件都不会被缓存

3 - 使用 v-show 复用 DOM

大家都知道,在日常开发中,v-show 使用的情况是非常少的。
因为与 v-if 相比,它仅仅是用 display: none 将节点隐藏了起来,
实际上节点依然是存在的,
一来这样实际上会增加内存成本,二来在权限管理的情况下,用户只要调出调试就可以绕过,非常不安全。

但这并意味着 v-show 就真的一无是处,相反在某些情况下,使用 v-show 的性能是优于 v-if 的,我们来看个例子:
  <div class="cell">
      <div v-show="isOn" class="on">
          <Heavy :n="999999">
      </div>
  </div>
</template>
假如 Heavy 是一个数据量庞大,并且逻辑复杂的组件,如果使用 v-if,则每次满足条件的时候,都需要将 Heavy 渲染一遍,而 v-show 则会将节点保存下来,当满足条件的时候直接改变其 display 令其渲染即可:这是典型的空间换时间的操作。

4 - 避免同时使用 v-if 和 v-for

  <ul>
    <li v-for="user in activeUsers" :key="user.id">{{ user.name }}</li>
  </ul>
</template>

<script>
export default {
  data: () => {
    return {
      users: [
        { name: "alice", isActive: false },
        { name: "bob", isActive: true },
        { name: "cindy", isActive: true }
      ]
    };
  },
  computed: {
    activeUsers: () => {
      return this.users.filter(user => user.isActive);
    }
  }
};
</script>

5 - 长列表性能优化

对于长列表,通常分两种情况来优化。

一是静态列表:如果这个列表仅仅用于数据的展示,不会有任何数据变化,那么就不需要作响应式处理。但由于 vue data 天生就是响应式的,所以我们可以利用 Object.freeze 将其冻结起来。(事实上也可以直接用 Object.defineProperty 直接去掉响应式)

  data: () => {
    return {
      users: [
        /* a long static list */
      ]
    };
  },
  async create() {
    const users = await axios.get("/users");
    this.users = Object.freeze(users);
  }
};

二是虚拟滚动:对于大数据的长列表,如果一次性全部渲染,显然是非常消耗性能的,所以我们可以采用虚拟滚动技术,只渲染被展示出来的部分(这方面的库有:vue-virtual-scroller, vue-virtual-scroll-list,具体使用参考文档即可)

    <template>
        <FetchItemView :item="item" @vote="voteItem(item)"/>
    </template>
</recycle-scroller>

6 - 销毁事件避免内存泄漏

我们知道,在 vue 组件销毁的时候,会自动解绑它的全部指令以及事件监听器,但这仅限于组件本身的事件,不包括定时器。所以如果一个组件有使用到定时器,最好在组件销毁的时候同时销毁定时器,防止内存泄漏。

export default {
  created() {
    this.timer = setInterval(this.refresh, 1000);
  },
  beforeDestroy() {
    clearInterval(this.timer);
  }
};

7 - 图片懒加载

图片加载是个老生常谈的问题了,在 vue 中也有非常好用的库(如 vue-lazyload)可以方便的实现这个功能。(事实上 chrome 也支持使用 lazyload 方便的设置图片懒加载)

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

8 - 按需引入第三方插件

相信大家平时在使用第三方组件库的时候都是直接整体引入的,比如下面例子中的 element ui:

import Vue from 'vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

事实上很多项目并不会用到组件库中的所有组件,这样的引入显然是有优化空间的,比如向下面这样按需引入(这点 antd 是真的很好):

import Vue from 'vue'
import { Button, Input } from 'element-ui';

Vue.use(Button);
Vue.use(Input);

9 - 无状态组件

这个可能平时用到的并不是很多,对于没有状态,完全用于展示的组件来说,我们可以利用 functional 将其设置为无状态组件,也就类似于 react 中的函数组件(没有 hooks 之前)

<template functional>
  <div class="cell">{{ value }}</div>
</template>

<script>
export default {
  props: ["value"]
};
</script>

10 - 变量本地化

这个技巧不仅仅在 vue 中,在其他地方也都非常常用。

export default {
  props: ["start"],
  computed: {
    base: () => 42,
    result: () => {
      const base = this.base;
      let result = this.start;
      for (let i = 0; i < 99999; i++) {
        result += heavy(base); // 这里是复杂的运算
      }
      return result;
    }
  }
};

可以预见,如果这里没有将 base 本地化保存,每次取用 base 都会经过一系列复杂的 vue 内部流程,性能消耗和取一个本地静态变量是不可同日而语的。

事实上,在函数的开始将需要用到的变量本地化保存是一个非常不错的习惯。

11 - SSR

这也是一个非常热门的话题,vue 的话结合 nuxt 可以很好的做到同构开发。

而 SSR 显著的优势主要有两点:

优化 SEO

优化首屏渲染速度

相关推荐
  • 首屏加载慢优化(性能优化)
  • Vuex的Module(哎,这个太重要了,不得不看啊)
评论
  • 蛮吉
    蛮吉 蛮吉

    来一份简历 邮件dataff@dingtalk.com~~你对技术的渴求就是我们对你的渴求