目录
什么是Pinia呢?
我们都已经有 Vuex 了为什么还要用 Pinia 呢
与 Vuex 相比,Pinia 有很多的优势
安装pinia
定义一个存储库 Store
认识 Store
定义一个store
使用定义的Store
操作State(一)
操作State(二)
认识和定义Getters
访问Getters
认识和定义Actions
Actions执行异步操作
什么是Pinia呢?
◼ Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近piña(西班牙语中的菠萝)的词;
Pinia开始于大概2019年,最初是作为一个实验为Vue重新设计状态管理,让它用起来像组合式API(Composition API)。
从那时到现在,最初的设计原则依然是相同的,并且目前同时兼容Vue2、Vue3,也并不要求你使用Composition API;
Pinia本质上依然是一个状态管理的库,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样);
我们都已经有 Vuex 了为什么还要用 Pinia 呢
Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队 讨论中的许多想法;
最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以最终决定用Pinia来代替Vuex;
与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的仪式,提供了 Composition-API 风格的 API;
最终要的是,在与 TypeScript 一起使用时具有可靠的类型判断支持;
与 Vuex 相比,Pinia 有很多的优势
比如 mutations 不再存在:
√ 他们经常被认为是 非常冗长;
√ 他们最初带来的 devtools 集成,但这不再是问题;
更友好的TypeScript支持,Vuex 之前对TS的支持很不友好;
不再有modules的嵌套结构:
√ 你可以灵活使用每一个 store,他们是通过扁平化的方式来相互使用的;
也不会再有命名空间的概念,不需要记住他们的复杂关系;
安装pinia
用你最喜欢的包管理器安装 pinia
:
yarn add pinia# 或者使用 npmnpm install pinia
定义一个存储库 Store
import { createPinia } from "pinia"const pinia = createPinia()export default pinia
在vue工程目录下的src目录下创建一个 stores 文件下 然后创建一个 index.js的文件 并且在idnex.js文件内创建pinia并导出 之后在 main.js里引入并且使用 stores
import pinia from './stores'createApp(App).use(pinia).use(router).mount('#app')
认识 Store
◼ 什么是Store?
一个 Store (如 Pinia)是一个实体,它会持有为绑定到你组件树的状态和业务逻辑,也就是保存了全局的状态;
它有点像始终存在,并且每个人都可以读取和写入的组件;
你可以在你的应用程序中定义任意数量的Store来管理你的状态;
◼ Store有三个核心概念:
state、getters、actions;
等同于组件的data、computed、methods;
一旦 store 被实例化,你就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性;
定义一个store
我们需要知道 Store 是使用 defineStore() 定义的,
并且它需要一个唯一名称,作为第一个参数传递;
import { defineStore } from "pinia"const useCounter = defineStore('count', { // defineStore(id(一个储存库标识)) state: () => ({ username: '桥志', age: 20, like: 'watermelon-ice', users: [ { id: 1, name: 'HachimanC', age: 18 }, { id: 2, name: '大吉', age: 20 }, { id: 3, name: '桥志三', age: 21 } ] })})export default useCounter
◼ 这个 name,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。
◼ 返回的函数统一使用useX作为命名方案,这是约定的规范;
使用定义的Store
◼ Store在它被使用之前是不会创建的,我们可以通过调用use函数来使用Store:
<div>姓名: {{ username }}</div> <div>年龄: {{ age }}</div> <div>喜欢: {{ like }}</div><script setup>import useInfo from '@/stores/information'import { toRefs } from 'vue'import { storeToRefs } from 'pinia'const infoStore = useInfo()const {username} = infoStore // 不是响应式const { username } = toRefs(infoStore) // 是响应式const { username, age, like } = storeToRefs(infoStore) // 是响应式</script>
◼ 注意Store获取到后不能被解构,那么会失去响应式:
为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()。
操作State(一)
◼ 读取和写入 state:
默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态;
const editPiniaHandler = () => { // 一个一个修改 infoStore.username += '三' infoStore.age += 1 infoStore.like = 'girl'}
◼ 重置 State:
你可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值;
const resetPiniaHandler = () => { infoStore.$reset()}
操作State(二)
◼ 改变State:
除了直接用 store.counter++ 修改 store,你还可以调用 $patch 方法;
它允许您使用部分“state”对象同时应用多个更改;
// 一次性修改 infoStore.$patch({ username: 'HachimanC', age: 21, })
◼ 替换State:
您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态:
// 替换 state 为新对象 const oldState = infoStore.$state useInfo.$state = { name: 'HachimanC', age: '22', like: 'girl', } console.log(oldState === infoStore.$state)
认识和定义Getters
◼ Getters相当于Store的计算属性:
它们可以用 defineStore() 中的 getters 属性定义;
getters中可以定义接受一个state作为参数的函数;
访问Getters
◼ Getters中访问自己的其他Getters:
我们可以通过this来访问到当前store实例的所有其他属性;
◼ Getters也可以返回一个函数,这样就可以接受参数:
<!-- getters使用部分 --> <div>doubleAge: {{ infoStore.doubleAge }}</div> <div>doubleAgeAddOne: {{ infoStore.doubleAgeAddOne }}</div> <div>查找id是2的用户: {{ infoStore.getUserById(2) }}</div> <div>查找id是3的用户: {{ infoStore.getUserById(3) }}</div> <div>getters使用其他储存库信息: {{ infoStore.showMessage }}</div> <hr />
认识和定义Actions
◼ Actions 相当于组件中的 methods。
可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑;
◼ 和getters一样,在action中可以通过this访问整个store实例的所有操作;
Actions执行异步操作
◼ Actions中是支持异步操作的,并且我们可以编写异步函数,在函数中使用await;
<!-- avtions 使用部分 --> <div>{{ infoStore.age }}</div> <button @click="addAgeHandler">actions操作</button> <!-- 展示avtions异步请求来的数据 --> <ul> <template v-for="item in homeStore.banners" :key="item"> <li>{{item.title}}</li> </template> </ul>