文章目录
- 前言
- 一、解构的注意事项
- 二、注意创建和使用顺序
- 总结
前言
在采用Pinia进行状态管理时,总结了一些关键注意事项与实战经验,旨在优化开发流程并确保高效利用其功能。这包括了正确规划存储结构、充分利用响应式优势、妥善处理模块化以促进代码可维护性,以及重视类型安全和测试策略的实施,以期在Vue应用中实现状态管理的最佳实践。"
一、解构的注意事项
1、请注意,store 是一个用 reactive 包装的对象,这意味着不需要在 getters 后面写 .value。就像 setup 中的 props 一样,我们不能对它进行解构,
<script setup>
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
// ❌ 这将不起作用,因为它破坏了响应性
// 这就和直接解构 `props` 一样
const { name, doubleCount } = store
name // 将始终是 "Eduardo"
doubleCount // 将始终是 0
setTimeout(() => {store.increment()
}, 1000)
// ✅ 这样写是响应式的
// 💡 当然你也可以直接使用 `store.doubleCount`
const doubleValue = computed(() => store.doubleCount)
</script>
为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>
在使用Pinia进行Vue状态管理时,直接解构store中的state、getters或actions可能会导致响应式丢失。因此,遵循以下注意事项是非常重要的:
避免直接解构state: 如果直接从store中解构state属性,例如 const { count } = useCounterStore(),解构后的变量将不再是响应式的。这意味着Vue无法自动追踪这些变量的变化并触发视图更新。
使用storeToRefs保持响应式: 为了解构state并保持其响应式,你应该使用storeToRefs函数。这个函数来自于pinia库,可以将store的refs转换为普通的ref,从而保持响应式。
区分ref和非ref属性: 使用storeToRefs时,它只会转换store中的ref属性(通常是state),而不会包括actions或非响应式的属性。actions需要单独从store中提取,并且不需要也不应该使用storeToRefs。
在模板中直接访问: 在Vue模板中,你可以直接使用store的属性和方法,它们会被自动追踪,无需担心响应式问题。但在setup脚本中使用解构时,遵循上述规则。
更新逻辑中的使用: 当在方法或计算属性中使用解构的变量时,确保使用.value访问其实际值,因为它们是ref对象。例如:console.log(count.value)。
二、注意创建和使用顺序
Pinia store 依靠 pinia 实例在所有调用中共享同一个 store 实例。大多数时候,只需调用你定义的 useStore() 函数,完全开箱即用。例如,在 setup() 中,你不需要再做任何事情。但在组件之外,情况就有点不同了。实际上,useStore() 给你的 app 自动注入了 pinia 实例。这意味着,如果 pinia 实例不能自动注入,你必须手动提供给 useStore() 函数。你可以根据不同的应用,以不同的方式解决这个问题。
如果你不做任何 SSR(服务器端渲染),在用 app.use(pinia) 安装 pinia 插件后,对 useStore() 的任何调用都会正常执行
import { useUserStore } from '@/stores/user'
import { createApp } from 'vue'
import App from './App.vue'// ❌ 失败,因为它是在创建 pinia 之前被调用的
const userStore = useUserStore()const pinia = createPinia()
const app = createApp(App)
app.use(pinia)// ✅ 成功,因为 pinia 实例现在激活了
const userStore = useUserStore()
为确保 pinia 实例被激活,最简单的方法就是将 useStore() 的调用放在 pinia 安装后才会执行的函数中。
让我们来看看这个在 Vue Router 的导航守卫中使用 store 的例子。
import { createRouter } from 'vue-router'
const router = createRouter({// ...
})// ❌ 由于引入顺序的问题,这将失败
const store = useStore()router.beforeEach((to, from, next) => {// 我们想要在这里使用 storeif (store.isLoggedIn) next()else next('/login')
})router.beforeEach((to) => {// ✅ 这样做是可行的,因为路由器是在其被安装之后开始导航的,// 而此时 Pinia 也已经被安装。const store = useStore()if (to.meta.requiresAuth && !store.isLoggedIn) return '/login'
})
总结
由官方文档而来觉得必须要注意到注意事项,备忘避雷。