开个玩笑,这里说的菠萝不是吃的,是vue3中的状态管理器(pinia)
在学习 Vue2 的一定都知道,在 vue2 版本中,如果想要使用状态管理器,那么一定是集成 Vuex,首先说明一点,Vuex 在 vue3 项目中依旧是可以正常使用的,是 vue 项目的正规军。但是,今天我们学习一下菠萝,Pinia 目前也已经是 vue 官方正式的状态库。适用于 vue2 和 vue3。可以简单的理解成 Pinia 就是 Vuex5。也就是说, Vue3 项目,建议使用Pinia,当然很多公司或者是项目由 vue2 转为 vue3 之后,由于习惯了使用 vuex ,所以说,在 vue3 当中继续使用 vuex 的,也不是少数,都知道就可以,根据实际情况来选择。
首先先来了解一下
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。Pinia 的成功可以归功于他管理存储数据的独特功能,例如:可扩展性、存储模块组织、状态变化分组、多存储创建等。
Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队讨论中的许多想法。最终,意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分内容,并决定实现它 取而代之的是新的建议。
现在官方网站的生态推荐已经将Vuex换成了Pinia
Pinia 被 vue 纳入正规编制,肯定是有原因的,那 pinia 有啥优点呢,主要是一下几点:
pinia 符合直觉,易于学习。
pinia 是轻量级状态管理工具,大小只有1KB.
pinia 模块化设计,方便拆分。
pinia 没有 mutations,直接在 actions 中操作 state,通过 this.xxx 访问响应的状态,尽管可以直接操作 state,但是还是推荐在 actions 中操作,保证状态不被意外的改变。
store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或者是 MapAction 辅助函数,这是在 Vuex 中很常见的。
支持多个 store。
支持 Vue devtools、SSR、webpack 代码拆分。
与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的仪式,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持。
总结以下五点:
搭建项目并安装Pinia,执行安装Pinia
yarn add pinia
// or
npm i pinia
首先在main.js中引入pinia
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'//创建一个 pinia(根存储)并将其传递给应用程序:
createApp(App).use(createPinia()).mount('#app')
在src目录下创建一个store文件夹,并新建index.js,写入以下内容:
import { defineStore } from 'pinia'
// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main', {
? // other options...
? state: () => {
? ? return {
? ? ? msg: 'hello world!',
? ? ? count: 0
? ? }
? },
? getters: {},
? actions: {}
})
defineStore() 定义Store,并且它需要一个唯一名称,作为第一个参数传递
参数:
第一个参数:相当于为容器起一个名字。注意:这里的名字必须唯一,不能重复。
第二个参数:一个配置对象,里边是对容器仓库的配置说明。
state 属性: 用来存储全局的状态的
getters属性: 类似计算属性,用来监视或者说是计算状态的变化的,有缓存的功能。
actions属性: 修改state,对state里数据变化的业务逻辑,需求不同,编写逻辑不同
两种方法
第一种:之间使用整个store取值
第二种:结构取值,但不要直接结构store
storeToRefs:为了从 Store 中提取属性同时保持其响应式, 它将为任何响应式属性创建 refs
实例:
<template>
? <div>{{ store.msg }}</div>
? <div>{{ msg }}</div>
</template>
<script setup>
import { useStore } from '@/store/index';
import { storeToRefs } from "pinia";
let store = useStore()
// 不要直接结构,会破坏响应式,使用storeToRefs
// const { msg } = store;
const { msg } = storeToRefs(store);
</script>
直接修改
<template>
? <div>{{ store.count }}</div>
? <button @click="add">+1</button>
</template>
<script setup>
import { useStore } from '@/store/index';
let store = useStore()
const add = () => {
? store.count++
}
</script>
调用$patch
这个方法可以修改多个状态
<template>
? <div>{{ store.count }}</div>
? <button @click="add">+1</button>
</template>
<script setup>
import { useStore } from '@/store/index';
let store = useStore()
const add = () => {
? store.$patch({
? ? count: store.count + 1,
? ? msg: 'hello pinia!'
? })
}
</script>