性能优化 #
性能问题来源 #
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