Vue3实战笔记(18)—pinia注意事项和经验总结

62 篇文章 2 订阅
62 篇文章 2 订阅


前言

在采用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) => {
  // 我们想要在这里使用 store
  if (store.isLoggedIn) next()
  else next('/login')
})

router.beforeEach((to) => {
  // ✅ 这样做是可行的,因为路由器是在其被安装之后开始导航的,
  // 而此时 Pinia 也已经被安装。
  const store = useStore()

  if (to.meta.requiresAuth && !store.isLoggedIn) return '/login'
})

总结

由官方文档而来觉得必须要注意到注意事项,备忘避雷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值