赞
踩
1. pinia是什么?
- 在
Vue3
中,可以使用传统的Vuex
来实现状态管理,也可以使用最新的pinia
来实现状态管理,我们来看看官网如何解释pinia
的:Pinia
是Vue
的存储库,它允许您跨组件/页面共享状态。- 实际上,
pinia
就是Vuex
的升级版,官网也说过,为了尊重原作者,所以取名pinia
,而没有取名Vuex
,所以大家可以直接将pinia
比作为Vue3
的Vuex
2. 为什么要使用pinia?
Vue2
和Vue3
都支持,这让我们同时使用Vue2
和Vue3
的小伙伴都能很快上手。pinia
中只有state
、getter
、action
,抛弃了Vuex
中的Mutation
,Vuex
中mutation
一直都不太受小伙伴们的待见,pinia
直接抛弃它了,这无疑减少了我们工作量。pinia
中action
支持同步和异步,Vuex
不支持Typescript
支持,毕竟我们Vue3
都推荐使用TS
来编写,这个时候使用pinia
就非常合适了Vuex
中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而pinia
中每个store
都是独立的,互相不影响。1KB
左右。pinia
支持插件来扩展自身功能。3. pinna使用
我们这里搭建一个最新的Vue3 + TS + Vite
项目
npm create vite@latest my-vite-app --template vue-ts
pinia
基础使用yarn add pinia
// main.ts
import {
createApp } from "vue";
import App from "./App.vue";
import {
createPinia } from "pinia";
const pinia = createPinia();
const app = createApp(App);
app.use(pinia);
app.mount("#app");
2.1 创建store
//sbinsrc/store/user.ts
import {
defineStore } from 'pinia'
// 第一个参数是应用程序中 store 的唯一 id
export const useUsersStore = defineStore('users', {
// 其它配置项
})
创建store
很简单,调用pinia
中的defineStore
函数即可,该函数接收两个参数:
name
:一个字符串,必传项,该store
的唯一id
。options
:一个对象,store
的配置项,比如配置store
内的数据,修改数据的方法等等。我们可以定义任意数量的store
,因为我们其实一个store
就是一个函数,这也是pinia
的好处之一,让我们的代码扁平化了,这和Vue3
的实现思想是一样的
2.2 使用store
<!-- src/App.vue -->
<script setup lang="ts">
import {
useUsersStore } from "../src/store/user";
const store = useUsersStore();
console.log(store);
</script>
2.3 添加state
export const useUsersStore = defineStore("users", {
state: () => {
return {
name: "test",
age: 20,
sex: "男",
};
},
});
2.4 读取state
数据
<template> <img alt="Vue logo" src="./assets/logo.png" /> <p>姓名:{ { name }}</p> <p>年龄:{ { age }}</p> <p>性别:{ { sex }}</p> </template> <script setup lang="ts"> import { ref } from "vue"; import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); const name = ref<string>(store.name); const age = ref<number>(store.age); const sex = ref<string>(store.sex); </script>
上段代码中我们直接通过store.age
等方式获取到了store
存储的值,但是大家有没有发现,这样比较繁琐,我们其实可以用解构的方式来获取值,使得代码更简洁一点
import {
useUsersStore, storeToRefs } from "../src/store/user";
const store = useUsersStore();
const {
name, age, sex } = storeToRefs(store); // storeToRefs获取的值是响应式的
2.5 修改state
数据
<template> <img alt="Vue logo" src="./assets/logo.png" /> <p>姓名:{ { name }}</p> <p>年龄:{ { age }}</p> <p>性别:{ { sex }}</p> <button @click="changeName">更改姓名</button> </template> <script setup lang="ts"> import child from './child.vue'; import { useUsersStore, storeToRefs } from "../src/store/user"; const store = useUsersStore(); const { name, age, sex } = storeToRefs(store); const changeName = () => { store.name = "张三"; console.log(store); }; </script>
2.6 重置state
state
数据,想要将它还原,这个时候该怎么做呢?就比如用户填写了一部分表单,突然想重置为最初始的状态。store
的$reset()
方法即可,继续使用我们的例子,添加一个重置按钮<button @click="reset">重置store</button>
// 重置store
const reset = () => {
store.$reset();
};
当我们点击重置按钮时,store
中的数据会变为初始状态,页面也会更新
2.7 批量更改state
数据
如果我们一次性需要修改很多条数据的话,有更加简便的方法,使用store
的$patch
方法,修改app.vue
代码,添加一个批量更改数据的方法
<button @click="patchStore">批量修改数据</button>
// 批量修改数据
const patchStore = () => {
store.$patch({
name: "张三",
age: 100,
sex: "女",
});
};
state
中有些字段无需更改,但是按照上段代码的写法,我们必须要将state中的所有字段例举出了。pinia
提供的$patch
方法还可以接收一个回调函数,它的用法有点像我们的数组循环回调函数了。store.$patch((state) => {
state.items.push({
name: 'shoes', quantity: 1 })
state.hasChanged = true
})
2.8 直接替换整个state
pinia
提供了方法让我们直接替换整个state
对象,使用store
的$state
方法
store.$state = {
counter: 666, name: '张三' }
上段代码会将我们提前声明的state
替换为新的对象,可能这种场景用得比较少
getters
属性getters
是defineStore
参数配置项里面的另一个属性getter
想象成Vue
中的计算属性,它的作用就是返回一个新的结果,既然它和Vue
中的计算属性类似,那么它肯定也是会被缓存的,就和computed
一样3.1 添加getter
export const useUsersStore = defineStore("users", { state: () => { return { name: "test", age: 10, sex: "男", }; }, getters: { getAddAge: (state) => { return state.age + 100; }, }, })
上段代码中我们在配置项参数中添加了getter
属性,该属性对象中定义了一个getAddAge
方法,该方法会默认接收一个state
参数,也就是state
对象,然后该方法返回的是一个新的数据
3.2 使用getter
<template> <p>新年龄:{ { store.getAddAge }}</p> <button @click="patchStore">批量修改数据</button> </template> <script setup lang="ts"> import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); // 批量修改数据 const patchStore = () => { store.$patch({ name: "张三", age: 100, sex: "女", }); }; </script>
上段代码中我们直接在标签上使用了store.gettAddAge
方法,这样可以保证响应式,其实我们state
中的name
等属性也可以以此种方式直接在标签上使用,也可以保持响应式
3.3 getter
中调用其它getter
export const useUsersStore = defineStore("users", { state: () => { return { name: "test", age: 20, sex: "男", }; }, getters: { getAddAge: (state) => { return state.age + 100; }, getNameAndAge(): string { return this.name + this.getAddAge; // 调用其它getter }, }, });
3.3 getter
传参
export const useUsersStore = defineStore("users", {
state: () => {
return {
name: "test",
age: 20
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。