关于Pinia
如果你之前使用过Vue2.0的状态管理Vuex,那么上手Pinia将会变的十分简单
核心部分 Store
- store是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定;换句话说,它承载着全局状态;它有点像一个永远存在的组件,每个组件都可以读取和写入它
- store它有三个概念,state、getters和actions,我们可以l理解成组件中的data、computed和methods
- 在项目中的src\store文件夹下不同的store.js文件
- store是用defineStore(name, function | options)定义的,建议其函数返回的值命名为use…Store方便理解
a. 参数name:名字,必填值且唯一
b. 参数function|options:可以是对象或函数形式
■ 对象形式【选项模式】,其中配置state、getters和actions选项
■ 函数形式【组合模式,类似组件组合式API的书写方式】,定义响应式变量和方法,并且return对应的变量和方法;ref()相当于state,computed()相当于getters,function()相当于actions
Store中的State
state是store的核心部分,主要存储的是共享的数据
- . store采用的是选项式模式时,state选项为函数返回的对象,在其定义共享的数据
- . store采用的是组合式模式时,在其函数内定义的ref变量,最终return出去来提供共享的数据
// 这里举例都用组合式api
import {defineStore} from "pinia";
import {ref} from "vue";
export const useUserStore = defineStore('user', () => {
const age = ref(27)
const level = ref(5)
const account = ref('SD77842')
const nickname = ref('二十四桥明月夜')
return { age, level, account, nickname } // 将数据暴露出去,共享给需要的组件
})
组件中访问State
- 在选项式 API 组件中,可以使用mapState(storeObj, array | object)帮助器将状态属性映射为只读计算属性
a. storeObj引入的store对象
b. array | object:字符串数组形式或者对象形式
■ 【字符串数组形式】直接将store中state的数据映射为当前组件的计算属性,但是不能自定义名称
■ 【对象形式时】key为自定义当前组件的计算属性名,value字符串形式,是store中state的共享数据
提示:mapState()函数映射到组件中的计算属性是只读的,如果想在组件中响应式修改state的数据,则应该选择mapWritableState()函数来映射计算属性 - 在组合式 API 组件中,直接引入对应的store,通过store对象直接获取和修改state
提示:
如果想在组件中自定义变量来接收store中的state中共享的数据,我们可以这样做:
● 使用computed(() => store.dataName),具有响应式,但是只读形式
● 使用storeToRefs(store)从store解构想要的state,具有响应式,可直接修改,可自定义名称
<script setup>
import { useUserStore } from "@/stores/counter.js";
import { storeToRefs } from "pinia";
import { computed } from "vue";
import UserVue from '@/components/User.vue'
// 获取 UserStore 实例
const user_store = useUserStore();
// 通过computed()将store中state映射到当前计算属性,具有响应性,但是是只读的
const user_age = computed(() => user_state.age);
const user_level = computed(() => user_state.level);
const user_account = computed(() => user_state.account);
const user_nickname = computed(() => user_state.nickname);
// storeToRefs 将store中state解构为组件的数据,具有响应式,还可以响应式修改
const {
age,
level,
account: userAccount,
nickname: userNickname,
} = storeToRefs(user_store);
</script>
Store中的Getters
getters是计算得到的新的共享数据,当依赖的数据发生变化时则重新计算,所以其他组件包括store自己不要直接对其修改
- store采用的是选项式模式时,getters选项中声明的函数即为计算属性
a. 在其函数内可通过this关键字来获取store实例,也可通过方法的第一个参数得到store实例
b. 如果采用的是箭头函数的话,无法使用this关键字,为了更方便使用store中实例,可为其箭头函数设置第一个参数来获取store实例 - store采用的是组合式模式时,可通过computed()函数通过计算得到新的数据,再将其return暴露出去即可
import { defineStore } from "pinia"
import { computed, ref } from "vue"
export const useUserStore = defineStore('user', () => {
const birthday = ref('1992-12-27')
const age = ref(30)
// 声明通过计算得到的共享数据,是只读的,如果依赖的数据发生变化则会重新计算
const month = computed(() => {
return birthday.value.split('-')[1]
})
const ageStage = computed(() => {
if (age.value < 18) return '未成年'
if (age.value < 35) return '青年'
if (age.value < 50) return '中年'
if (age.value >= 50) return '老年'
})
return { birthday, age, month, ageStage }
})
在组件中使用Getters
- 选项式API的组件中,访问store中的getters和访问state类似,同样可使用mapState()帮助器将getters属性映射为只读计算属性
注意:如果采用mapWritableState()帮助器将store中的getters映射为组件内部的计算属性,依旧可以具有响应式,一旦对其进行修改则会报错 - 在组合式API组件中,访问store中的getters和访问state类似,直接引入对应的store,通过store对象直接获取getters,但是如果对其进行修改则会报错
提示:
如果想将store中的getter中共享的数据映射为本地组件的计算属性,我们可以这样做:
● 使用computed(() => store.getterName),具有响应式,但是只读形式
● 使用storeToRefs(store)从store解构getter依旧
<script setup>
import { storeToRefs } from "pinia";
import { computed } from "vue";
import { useUserStore } from "@/stores/counter.js";
// store实例,可以直接通过store获取getters,但是是只读的,如果一旦修改则会报错
const user_store = useUserStore();
// 通过computed将getters映射为自己的计算属性,但是是只读的,如果一旦修改则会警告
const birthday_month = computed(() => user_store.month);
const user_age_stage = computed(() => user_store.ageStage);
// 通过storeToRefs将getters解构为自己的计算属性,但是是只读的,如果一旦修改则会警告
const { month, ageStage: userAgeStage } = storeToRefs(user_store);
// 将 state 解构为自己的数据
const { birthday, age } = storeToRefs(user_store);
</script>
Store中的Actions
actions一般情况下是对state中的数据进行修改的业务逻辑函数,actions也可以是异步的,你可以在其中await任何API调用甚至其他操作
- store采用的是选项式模式时,actions选项中声明的函数即可共享其函数,在其函数内可通过this来获取整个store实例
- store采用的是组合式模式时,可通过声明函数,再将其return暴露出去即可共享其函数
import {defineStore} from "pinia"
import {ref} from "vue";
export const useUserStore = defineStore('user', () => {
const nickname = ref('自古风流')
const age = ref(20)
// 定义函数(注意:形参不要和 ref 名冲突)
function setUserInfo(user_nickname, user_age) {
nickname.value = user_nickname
age.value = user_age
}
function setUserInfoByObject(user) {
// 可通过 `this` 来获取当前 store 实例
nickname.value = user.nickname
age.value = user.age
}
return {nickname, age, setUserInfo, setUserInfoByObject} // 暴露函数即可共享函数
})
组件中访问Actions
- 在选项式 API 组件中,可以使用mapActions(storeObj, array | object)帮助器将actions映射为当前组件的函数
a. storeObj引入的store对象
b. array | object:字符串数组形式或者对象形式
■ 【字符串数组形式】直接将store中actions的函数映射为当前组件的函数,但是不能自定义名称
■ 【对象形式时】key为自定义当前组件的函数名,value字符串形式,是store中actions的函数名 - 在组合式API组件中,直接引入对应的store,通过store对象直接获取actions
提示:如果想将store中的actions中函数映射为本地组件的函数,可将store解构出对应的函数即可,也可自定应函数名,此处不可通过storeToRefs(store)函数
<script setup>
import { useUserStore } from "@/stores/counter.js";
import { storeToRefs } from "pinia";
// 可直接使用 store 执行 actions
const user_store = useUserStore();
const { nickname, age } = storeToRefs(user_store);
// 可将 store 中的 actions 映射为自己的函数,可自定映射的函数名(不可使用 storeToRes 函数)
const { setUserInfo, setUserInfoByObject: set_user_info_object } = user_store;
</script>
文章总结
本文总结了Vue3.0 状态管理库Pinia的一些核心属性,
如果你想更多的了解Pinia可以看我之前的文章: Vue3.0 状态管理库Pinia的前世今生,
希望本文能对你有所帮助。