性能优化 #

性能问题来源 #

text
Vuex 性能问题来源
├── 过大的状态对象
├── 频繁的状态更新
├── 不必要的组件重渲染
├── 复杂的 Getter 计算
└── 深层嵌套的监听

状态优化 #

1. 扁平化状态 #

javascript
// 不推荐:深层嵌套
state: {
  data: {
    users: {
      list: {
        items: []
      }
    }
  }
}

// 推荐:扁平化
state: {
  users: {
    byId: {},
    allIds: []
  }
}

2. 规范化数据 #

javascript
// 不推荐:数据冗余
state: {
  posts: [
    { id: 1, title: 'Post 1', author: { id: 1, name: 'John' } },
    { id: 2, title: 'Post 2', author: { id: 1, name: 'John' } }
  ]
}

// 推荐:规范化
state: {
  posts: {
    byId: {
      1: { id: 1, title: 'Post 1', authorId: 1 },
      2: { id: 2, title: 'Post 2', authorId: 1 }
    },
    allIds: [1, 2]
  },
  users: {
    byId: {
      1: { id: 1, name: 'John' }
    }
  }
}

3. 分离 UI 状态 #

javascript
state: {
  // 业务数据
  entities: {
    users: {},
    products: {}
  },
  
  // UI 状态单独管理
  ui: {
    loading: false,
    error: null,
    selectedId: null
  }
}

Getter 优化 #

1. 缓存计算结果 #

javascript
// Getter 自动缓存
getters: {
  expensiveGetter: state => {
    // 复杂计算,但会被缓存
    return state.items.reduce((acc, item) => {
      // ...
    }, {})
  }
}

2. 避免返回新对象 #

javascript
// 不推荐:每次返回新对象
getters: {
  userOptions: state => {
    return state.users.map(u => ({ label: u.name, value: u.id }))
  }
}

// 推荐:使用缓存
getters: {
  usersMap: state => state.users,
  userOptions: (state, getters) => {
    // 只在 users 变化时重新计算
    return getters.usersMap.map(u => ({ label: u.name, value: u.id }))
  }
}

3. 延迟计算 #

javascript
// 使用函数延迟计算
getters: {
  filteredItems: state => filters => {
    // 只在调用时计算
    return state.items.filter(item => {
      return Object.entries(filters).every(([key, value]) => 
        item[key] === value
      )
    })
  }
}

// 使用
const result = store.getters.filteredItems({ category: 'books' })

组件优化 #

1. 精确订阅 #

javascript
// 不推荐:订阅整个对象
computed: {
  ...mapState(['user'])
}

// 推荐:只订阅需要的属性
computed: {
  userName() {
    return this.$store.state.user.name
  }
}

2. 使用 mapState 选择器 #

javascript
// 不推荐
computed: {
  user() {
    return this.$store.state.user
  }
}

// 推荐:使用选择器
computed: {
  ...mapState({
    userId: state => state.user.id,
    userName: state => state.user.name
  })
}

3. 避免过度使用 Getter #

javascript
// 简单访问直接使用 state
computed: {
  userName() {
    return this.$store.state.user.name  // 简单访问
  }
}

// 复杂计算使用 getter
computed: {
  filteredProducts() {
    return this.$store.getters.filteredProducts  // 复杂计算
  }
}

Mutation 优化 #

1. 批量更新 #

javascript
// 不推荐:多次提交
items.forEach(item => {
  commit('UPDATE_ITEM', item)
})

// 推荐:批量更新
commit('UPDATE_ITEMS', items)

2. 使用 Object.assign #

javascript
// 不推荐:逐个属性更新
commit('SET_NAME', name)
commit('SET_EMAIL', email)
commit('SET_AGE', age)

// 推荐:一次更新
commit('UPDATE_USER', { name, email, age })

Action 优化 #

1. 并行请求 #

javascript
// 不推荐:顺序请求
async fetchAll({ dispatch }) {
  await dispatch('fetchUsers')
  await dispatch('fetchProducts')
  await dispatch('fetchOrders')
}

// 推荐:并行请求
async fetchAll({ dispatch }) {
  await Promise.all([
    dispatch('fetchUsers'),
    dispatch('fetchProducts'),
    dispatch('fetchOrders')
  ])
}

2. 取消重复请求 #

javascript
let pendingRequest = null

actions: {
  async fetchData({ commit }) {
    // 取消之前的请求
    if (pendingRequest) {
      pendingRequest.abort()
    }
    
    pendingRequest = createAbortableRequest()
    
    try {
      const data = await pendingRequest.promise
      commit('SET_DATA', data)
    } finally {
      pendingRequest = null
    }
  }
}

3. 防抖搜索 #

javascript
let searchTimeout = null

actions: {
  search({ commit }, query) {
    return new Promise(resolve => {
      clearTimeout(searchTimeout)
      
      searchTimeout = setTimeout(async () => {
        const results = await api.search(query)
        commit('SET_RESULTS', results)
        resolve(results)
      }, 300)
    })
  }
}

模块优化 #

1. 按需加载模块 #

javascript
// 路由守卫中动态加载
router.beforeEach(async (to, from, next) => {
  if (to.meta.module && !store.hasModule(to.meta.module)) {
    const module = await import(`@/store/modules/${to.meta.module}`)
    store.registerModule(to.meta.module, module.default)
  }
  next()
})

2. 卸载不需要的模块 #

javascript
// 组件卸载时清理
onUnmounted(() => {
  if (store.hasModule('tempModule')) {
    store.unregisterModule('tempModule')
  }
})

严格模式 #

javascript
// 只在开发环境开启
const store = createStore({
  strict: process.env.NODE_ENV !== 'production'
})

// 生产环境关闭以提升性能

性能监控 #

1. 使用 Vue DevTools #

text
Vue DevTools 性能分析
├── 组件渲染时间
├── Vuex mutation 时间
├── 状态变化追踪
└── 性能瓶颈定位

2. 自定义性能监控 #

javascript
// 插件监控 mutation 耗时
const performancePlugin = store => {
  store.subscribe((mutation, state) => {
    const start = performance.now()
    
    // mutation 执行后
    requestAnimationFrame(() => {
      const duration = performance.now() - start
      if (duration > 16) {  // 超过一帧
        console.warn(`Slow mutation: ${mutation.type} took ${duration}ms`)
      }
    })
  })
}

最佳实践总结 #

优化点 方法
状态结构 扁平化、规范化
Getter 利用缓存、避免新对象
组件 精确订阅、避免过度使用
Mutation 批量更新
Action 并行请求、防抖
模块 按需加载、及时卸载

继续学习 常见问题,了解 Vuex 常见问题解答。

最后更新:2026-03-28