为什么你应该使用 Pinia?(借用官网)
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({}) 来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染,这可能会使你的应用暴露出一些安全漏洞。 而如果使用 Pinia,即使在小型单页应用中,你也可以获得如下功能:
Devtools 支持
追踪 actions、mutations 的时间线
在组件中展示它们所用到的 Store
让调试更容易的 Time travel
热更新
不必重载页面即可修改 Store
开发时可保持当前的 State
插件:可通过插件扩展 Pinia 功能
为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。
支持服务端渲染
!!
简单来说,就是方便,完美契合vue3,比vuex要更简洁
开始使用
注册与安装
npm i pinia
在src目录下创建store目录,在store目录下创建index.ts文件,文件内用来创建pinia
// store/index.ts
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
去main文件中注册
import pinia from '@/store/index.ts'
createApp(App).use(pinia)
模块化管理
在store目录下创建modules目录,然后创建对应的模块,例如user.ts
// store/modules/user.ts
import {defineStore} from 'pinia'
// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useUserInfoStore = defineStore('User', {
state: () => {
return {
count: 1
}
},
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
从上述例子,我们可以看到它与vuex的区别:
- 只有state,getters,actions,所有的方法都定义在
actions
里,并且方法不用在接受上下文参数,可以直接使用this
去访问state以及getters中定义好的数据。在getters
中,可以接受一个state参数,用来读取state中的数据,如果想访问其他getters的数据,通过this
去访问。 defineStore
第一个参数是这个仓库的唯一id
,你可以去devtools中去看到他的名字。第二个参数接受两种类型,当为一个函数时,我们可以像在vue3中的setup中写数据一样,需要引入ref等函数去帮助你完成响应式的数据,最后通过返回一个对象的形式去暴露,当为一个对象时,与上述例子相符。
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
// ref() 就是 state 属性
// computed() 就是 getters
// function() 就是 actions
vue中使用
<script setup>
import { useCounterStore } from '@/store/modules/user.ts'
// 可以在组件中的任意位置访问 `store` 变量 ✨
const store = useCounterStore()
</script>
请注意,store 是一个用 reactive
包装的对象,这意味着不需要在 getters 后面写 .value,就像 setup 中的 props 一样,如果你写了,我们也不能解构它:
<script setup>
const store = useCounterStore()
// ❌ 这将不起作用,因为它破坏了响应性
// 这就和直接解构 `props` 一样
const { count } = store
count // 将始终是 0
setTimeout(() => {
store.increment()
}, 1000)
// 如果你想解构属性,并且想拥有响应式,可以通过storeToRefs()
import { storeToRefs } from 'pinia'
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { count } = storeToRefs(store)
console.log(count.value)
// 当然如果是actions方法,你可以直接结构出来
const { increment } = store
</script>
参考
具体实例大家可以去看pinia官网,讲的很详细了。
pinia官网