Pinia 热更新 #
概述 #
热模块替换(HMR)允许在开发过程中更新 Store 的代码,而无需刷新整个页面。这对于保持应用状态、提高开发效率非常有用。
Vite 配置 #
基本配置 #
ts
// stores/index.ts
import { createPinia, acceptHMRUpdate } from 'pinia'
export const pinia = createPinia()
// 在 Vite 中配置 HMR
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(pinia))
}
单个 Store 的 HMR #
ts
// stores/counter.ts
import { defineStore, acceptHMRUpdate } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++
}
}
})
// 配置 HMR
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCounterStore))
}
统一配置 #
ts
// stores/index.ts
import { createPinia } from 'pinia'
export const pinia = createPinia()
// 统一导出所有 stores
export * from './user'
export * from './cart'
export * from './product'
ts
// main.ts
import { createApp } from 'vue'
import { pinia } from './stores'
import App from './App.vue'
const app = createApp(App)
app.use(pinia)
app.mount('#app')
// 配置 HMR
if (import.meta.hot) {
import.meta.hot.accept('./stores', (newStores) => {
// 重新加载所有 stores
})
}
Webpack 配置 #
基本配置 #
ts
// stores/counter.ts
import { defineStore, acceptHMRUpdate } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() { this.count++ }
}
})
// Webpack HMR
if (module.hot) {
module.hot.accept(acceptHMRUpdate(useCounterStore))
}
手动 HMR 处理 #
保留状态 #
ts
// stores/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: '',
email: '',
preferences: {
theme: 'light'
}
}),
actions: {
updateName(name: string) {
this.name = name
}
}
})
if (import.meta.hot) {
import.meta.hot.accept((newModule) => {
// 获取当前 store 实例
const store = useUserStore()
// 保存当前状态
const currentState = { ...store.$state }
// 更新 store 定义
newModule?.useUserStore
// 恢复状态
store.$patch(currentState)
})
}
使用 acceptHMRUpdate #
ts
import { defineStore, acceptHMRUpdate } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() { this.count++ }
}
})
// acceptHMRUpdate 会自动处理状态保留
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCounterStore))
}
HMR 工作原理 #
更新流程 #
text
1. 文件修改
↓
2. Vite/Webpack 检测到变化
↓
3. 触发 HMR 更新
↓
4. acceptHMRUpdate 处理更新
↓
5. 保留现有状态
↓
6. 更新 Store 定义
↓
7. 恢复状态
↓
8. 组件重新渲染
状态保留策略 #
ts
// 默认行为:保留所有状态
acceptHMRUpdate(useCounterStore)
// 自定义:选择性保留状态
if (import.meta.hot) {
import.meta.hot.accept((newModule) => {
const store = useCounterStore()
const { name, email } = store.$state // 只保留部分状态
// 更新 store
// ...
store.$patch({ name, email })
})
}
常见问题 #
1. Store ID 变化 #
如果修改了 Store 的 ID,HMR 可能无法正确工作:
ts
// 修改前
export const useUserStore = defineStore('user', { /* ... */ })
// 修改后
export const useUserStore = defineStore('userStore', { /* ... */ }) // ID 变化
// 解决方案:刷新页面
2. Setup Store 的 HMR #
Setup Store 的 HMR 需要特别注意:
ts
// stores/counter.ts
import { defineStore, acceptHMRUpdate } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, double, increment }
})
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCounterStore))
}
3. 跨 Store 引用 #
当 Store 之间有依赖关系时:
ts
// stores/cart.ts
import { defineStore, acceptHMRUpdate } from 'pinia'
import { useUserStore } from './user'
export const useCartStore = defineStore('cart', {
state: () => ({ items: [] }),
actions: {
checkout() {
const userStore = useUserStore()
// ...
}
}
})
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCartStore))
}
调试 HMR #
查看更新日志 #
ts
if (import.meta.hot) {
import.meta.hot.accept((newModule) => {
console.log('Store updated:', newModule)
})
}
使用 DevTools #
Vue DevTools 可以帮助你:
- 查看 Store 的当前状态
- 监控状态变化
- 追踪 HMR 更新
最佳实践 #
1. 始终配置 HMR #
ts
// 每个 store 文件末尾添加
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useXxxStore))
}
2. 使用 TypeScript #
ts
// 类型安全的 HMR
if (import.meta.hot) {
import.meta.hot.accept(
acceptHMRUpdate(useCounterStore, import.meta.hot)
)
}
3. 开发环境检测 #
ts
// 只在开发环境启用
if (import.meta.env.DEV && import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCounterStore))
}
下一步 #
现在你已经掌握了热更新,接下来让我们学习测试策略。
- 测试策略 - 单元测试与集成测试
最后更新:2026-03-28