什么是pinia?
Pinia 最初是在 2019 年 11 月左右重新设计使用 Composition API,可以理解为下一代 vuex,作者也称之为vuex5,同时vue已经将 pinia 收入 官方账户了
名字的由来
Pinia (发音为 /piːnjʌ/,类似英文中的 "peenya") 是最接近有效包名 piña (西班牙语中的 pineapple,即"菠萝") 的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的。 它(菠萝)也是一种原产于南美洲的美味热带水果。
为什么要用它?比vuex 强在哪里
pinia 最开始是一个实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库,来弥补vuex 的不足,且同时满足 vue2和vue3,下图是 pinia作者 总结的五点
- 1 同时支持 options(vue2)和composition api(vue3)
- 2 仅保留 state getters actions(取消了vuex 中 Mutation)
- 3 取消嵌套模块(取消了vuex 中 Module)
- 4 支持ts
- 5 透明 自动化的代码拆分
实际应用
项目创建 vite + vue3 + pinia
执行命令 npm create vite@latest 或 yarn create vite
sql
yarn create vite
// 或者npm create vite@latest
按照提示 输入项目名称、框架类型(必须是vue,因为pinia 只支持vue)、TypeScript
安装 pinia
csharp
yarn add pinia
挂载
打开main.ts
javascript
import { createPinia } from 'pinia'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
初始化 定义 Store
src 目录下 创建 index.ts
写法一 类似于 vuex的写法 没有mutations
user为容器(可以理解为命名空间)
javascript
import { defineStore } from 'pinia'
export const userStore = defineStore('user', {
state: () => {
return {
name: 'iwhao',
age: 18,
count: 1,
}
},
getters: {
countDouble: (state) => {
return state.count * 2
}
},
actions: {
countAdd() {
this.count++
}
}
})
写法二 composition api pinia 会自动识别 ref类型的 为 state 、computed类型的为 getter、function 为 action
javascript
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const userStore = defineStore('user', () => {
const name = ref('iwhao')
const age = ref(18)
const count = ref(1)
const countDouble = computed(() => count.value * 2)
function countAdd() {
count.value++
}
return { name, age, count, countDouble, countAdd }
})
使用
引用
这里直接在项目中components下的HelloWorld.vue 中写入案列
xml
<template>
<p>name: {{ user.name }}</p>
<p>age: {{ user.age }}</p>
<p>count: {{ user.count }}</p>
<p>countDouble: {{ user.countDouble }}</p>
<button @click="user.countAdd()">增加</button>
</template>
<script setup lang="ts">
import { userStore } from "../store/index";
const user = userStore();
</script>
效果如下
注意
不要直接解构使用,例如下方代码,因为这种写法 name, age, count, countDouble 将不会是响应式
css
...
<p>name: {{ user.name }}</p>
<p>age: {{ user.age }}</p>
<p>count: {{ user.count }}</p>
<p>countDouble: {{ user.countDouble }}</p>
<button @click="user.countAdd()">增加</button>
<br />
<p>name: {{ name }}</p>
<p>age: {{ age }}</p>
<p>count: {{ count }}</p>
<p>countDouble: {{ countDouble }}</p>
<button @click="user.countAdd()">增加</button>
...
const user = userStore();
const { name, age, count, countDouble } = user;
那如何让解构出来的变量 变成响应式呢,需要引入 storeToRefs
javascript
import { storeToRefs } from "pinia";
const { name, age, count, countDouble } = storeToRefs(user);
更新
第一种方法(不推荐,如果只是单变量更新的话无所谓)
ini
...
<button @click="upUser">更新</button>
...
const upUser = () => {
user.name = '张三'
user.age = 20
user.count = 100
}
如果批量更新多个,推荐使用 $patch
ini
...
<button @click="upUserBath">批量更新</button>
...
const upUserBath = () => {
user.$patch({
name: "张三",
age: 20,
count: 100,
});
};
// 或 这种写法
const upUserBath = () => {
user.$patch((state) => {
state.name = "张三";
state.age = 20;
state.count = 100;
});
};