Skip to content

Vue2 性能优化指南

1. 代码分割

路由懒加载

javascript
// 不好的写法
import UserProfile from '@/views/UserProfile.vue'

// 好的写法
const UserProfile = () => import('@/views/UserProfile.vue')

组件懒加载

javascript
// 不好的写法
import HeavyComponent from '@/components/HeavyComponent.vue'

// 好的写法
const HeavyComponent = () => import('@/components/HeavyComponent.vue')

2. 虚拟列表

使用 vue-virtual-scroller

vue
<template>
  <RecycleScroller
    class="scroller"
    :items="items"
    :item-size="32"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="user">
      {{ item.name }}
    </div>
  </RecycleScroller>
</template>

<script>
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

export default {
  components: {
    RecycleScroller
  }
}
</script>

3. 计算属性优化

避免复杂计算

javascript
// 不好的写法
computed: {
  filteredList() {
    return this.items
      .filter(item => item.active)
      .map(item => ({
        ...item,
        fullName: `${item.firstName} ${item.lastName}`
      }))
      .sort((a, b) => a.fullName.localeCompare(b.fullName))
  }
}

// 好的写法
computed: {
  activeItems() {
    return this.items.filter(item => item.active)
  },
  sortedItems() {
    return [...this.activeItems].sort((a, b) => 
      a.fullName.localeCompare(b.fullName)
    )
  }
}

4. 事件处理优化

防抖和节流

javascript
import { debounce, throttle } from 'lodash-es'

export default {
  created() {
    this.debouncedSearch = debounce(this.search, 300)
    this.throttledScroll = throttle(this.handleScroll, 200)
  },
  
  methods: {
    search() {
      // 搜索逻辑
    },
    handleScroll() {
      // 滚动处理逻辑
    }
  }
}

5. 列表渲染优化

使用 key

vue
<!-- 不好的写法 -->
<div v-for="item in items">
  {{ item.name }}
</div>

<!-- 好的写法 -->
<div v-for="item in items" :key="item.id">
  {{ item.name }}
</div>

避免 v-if 和 v-for 一起使用

vue
<!-- 不好的写法 -->
<div v-for="item in items" v-if="item.active">
  {{ item.name }}
</div>

<!-- 好的写法 -->
<div v-for="item in activeItems">
  {{ item.name }}
</div>

<script>
export default {
  computed: {
    activeItems() {
      return this.items.filter(item => item.active)
    }
  }
}
</script>

6. 组件优化

使用函数式组件

vue
<template functional>
  <div class="functional-component">
    {{ props.message }}
  </div>
</template>

合理使用 keep-alive

vue
<template>
  <keep-alive :include="['UserProfile', 'Settings']">
    <router-view />
  </keep-alive>
</template>

7. 图片优化

懒加载

vue
<template>
  <img v-lazy="imageUrl" />
</template>

<script>
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'error.png',
  loading: 'loading.gif',
  attempt: 1
})
</script>

使用 webp 格式

javascript
// 检测浏览器是否支持 webp
const checkWebpSupport = () => {
  const canvas = document.createElement('canvas')
  if (canvas.getContext && canvas.getContext('2d')) {
    return canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0
  }
  return false
}

8. 缓存优化

使用 localStorage

javascript
export default {
  methods: {
    saveToCache(key, data) {
      try {
        localStorage.setItem(key, JSON.stringify(data))
      } catch (e) {
        console.error('Cache error:', e)
      }
    },
    
    getFromCache(key) {
      try {
        const data = localStorage.getItem(key)
        return data ? JSON.parse(data) : null
      } catch (e) {
        console.error('Cache error:', e)
        return null
      }
    }
  }
}

9. 网络优化

使用 HTTP 缓存

javascript
// 配置 axios 实例
const api = axios.create({
  baseURL: process.env.VUE_APP_API_URL,
  headers: {
    'Cache-Control': 'max-age=3600'
  }
})

压缩资源

javascript
// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      new CompressionPlugin({
        test: /\.(js|css|html|svg)$/,
        threshold: 10240
      })
    ]
  }
}

10. 监控和性能分析

使用 Vue Performance Devtool

javascript
// main.js
import Vue from 'vue'
import VuePerformanceDevtool from 'vue-performance-devtool'

Vue.use(VuePerformanceDevtool)

性能指标监控

javascript
// 监控关键性能指标
export function monitorPerformance() {
  if ('performance' in window) {
    window.addEventListener('load', () => {
      const timing = performance.timing
      const metrics = {
        dns: timing.domainLookupEnd - timing.domainLookupStart,
        tcp: timing.connectEnd - timing.connectStart,
        request: timing.responseEnd - timing.requestStart,
        dom: timing.domComplete - timing.domLoading,
        load: timing.loadEventEnd - timing.navigationStart
      }
      console.log('Performance metrics:', metrics)
    })
  }
}

Released under the MIT License.