63 Vue中常见性能优化

Vue性能优化方式

  • 合理使用v-showv-if
  • 合理使用computed
  • v-for时添加key,以及避免和v-if同时使用
  • 自定义事件、DOM事件及时销毁
  • 合理使用异步组件,加载大组件
  • 合理使用keep-alive避免频繁重复渲染
  • data层级不要太深,避免递归性能不好
  • 使用vue-loader在开发环境做模板编译(预编译)
  • webpack层级优化
  • 前端通用性能优化,如图片懒加载
  • 使用SSR

编码优化

  1. 使用v-show复用DOM:避免重复创建组件
    <template>
      <div class="cell">
        <!-- 这种情况用v-show复用DOM,比v-if效果好 -->
        <div v-show="value" class="on">
          <Heavy :n="10000"/>
        </div>
        <section v-show="!value" class="off">
          <Heavy :n="10000"/>
        </section>
      </div>
    </template>
  1. 合理使用路由懒加载、异步组件 ,有效拆分App尺寸,访问时才异步加载
    const router = createRouter({
      routes: [
        // 借助webpack的import()实现异步组件
        { path: '/foo', component: () => import('./Foo.vue') }
      ]
    })
  1. keep-alive缓存页面:避免重复创建组件实例,且能保留缓存组件状态
    <router-view v-slot="{ Component }">
        <keep-alive>
        <component :is="Component"></component>
      </keep-alive>
    </router-view>
  1. v-oncev-memo:不再变化的数据使用v-once
    <!-- single element -->
    <span v-once>This will never change: {{msg}}</span>
    <!-- the element have children -->
    <div v-once>
      <h1>comment</h1>
      <p>{{msg}}</p>
    </div>
    <!-- component -->
    <my-component v-once :comment="msg"></my-component>
    <!-- `v-for` directive -->
    <ul>
      <li v-for="i in list" v-once>{{i}}</li>
    </ul>

按条件跳过更新时使用v-momo:下面这个列表只会更新选中状态变化项

    <div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
      <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
      <p>...more child nodes</p>
    </div>
  1. 长列表性能优化 :如果是大数据长列表,可采用虚拟滚动,只渲染少部分区域的内容
    <recycle-scroller
      class="items"
      :items="items"
      :item-size="24"
    >
      <template v-slot="{ item }">
        <FetchItemView
          :item="item"
          @vote="voteItem(item)"
        />
      </template>
    </recycle-scroller>
  1. 防止内部泄漏,组件销毁后把全局变量和事件销毁Vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件
    export default {
      created() {
        this.timer = setInterval(this.refresh, 2000)
      },
      beforeUnmount() {
        clearInterval(this.timer)
      }
    }
  1. 图片懒加载

对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载,等到滚动到可视区域后再去加载

    <!-- 参考 https://github.com/hilongjw/vue-lazyload -->
    <img v-lazy="/static/img/1.png">
  1. 滚动到可视区域动态加载

https://tangbc.github.io/vue-virtual-scroll-list (opens new window)

  1. 第三方插件按需引入:(babel-plugin-component

element-plus这样的第三方组件库可以按需引入避免体积太大

    import { createApp } from 'vue';
    import { Button, Select } from 'element-plus';

    const app = createApp()
    app.use(Button)
    app.use(Select)
  1. 服务端渲染:SSR

如果SPA应用有首屏渲染慢的问题,可以考虑SSR

以及下面的其他方法

  • 不要将所有的数据都放在data中,data中的数据都会增加gettersetter,会收集对应的watcher
  • v-for 遍历为 item 添加 key
  • v-for 遍历避免同时使用 v-if
  • 区分 computedwatch 的使用
  • 拆分组件(提高复用性、增加代码的可维护性,减少不必要的渲染 )
  • 防抖、节流

用户体验

  • app-skeleton 骨架屏
  • pwa serviceworker

SEO优化

  • 预渲染插件 prerender-spa-plugin
  • 服务端渲染 ssr

打包优化

  • Webpack 对图片进行压缩
  • 使用 cdn 的方式加载第三方模块
  • 多线程打包 happypack
  • splitChunks 抽离公共文件
  • 优化 SourceMap
  • 构建结果输出分析,利用 webpack-bundle-analyzer 可视化分析工具

基础的 Web 技术的优化

  • 服务端 gzip 压缩
  • 浏览器缓存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶颈
Last Updated:
Contributors: leeguooooo