Pinia使用
- Pinia简介
- 安装Pinia
- 存储数据和读取数据
- State
- 读取数据
- 重置 state
- 修改state值
- storeToRefs
- 监听state
- Getter
- 读取数据
- Action
Pinia简介
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。
安装Pinia
yarn add pinia
# 或者使用 npm
npm install pinia
创建一个 pinia 实例 (根 store) 并将其传递给应用:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
显示下图证明使用pinia成功
存储数据和读取数据
Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念,state、getter 和 action,我们可以假设这些概念相当于组件中的 data、 computed 和 methods。
Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字:
import { defineStore } from 'pinia'
// 你可以任意命名 `defineStore()` 的返回值,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。
// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts', {
// 其他配置...
})
有两种写法
选项式Store
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
组合式Store
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
在 Setup Store 中:
- ref() 就是 state 属性
- computed() 就是 getters
- function() 就是 actions
State
在 Pinia 中,state 被定义为一个返回初始状态的函数
import { defineStore } from 'pinia'
export const useUserStore = defineStore("user",{
state(){
return{
username : "xiaoc", //属性都将自动推断出它们的类型
age : 25,
poclist:[{ id: "dasdasdad01", title: "禅道 12.4.2 后台任意文件上传漏洞", content: "禅道 <= 12.4.2版本" },
{ id: "dasdasdad02", title: "Rails sprockets 任意文件读取漏洞", content: "Sprockets < 3.7.1" },
{ id: "dasdasdad03", title: "Rails sprockets 任意文件读取漏洞", content: "Sprockets < 3.7.1" },
{ id: "dasdasdad04", title: "HiKVISION 综合安防管理平台 report 任意文件上传漏洞", content: "HiKVISION 综合安防管理平台" }]
}
}
})
读取数据
默认情况下,你可以通过 store 实例访问 state,直接对其进行读写。
import {useUserStore} from '@/store/user'
const userStore =useUserStore()
console.log(userStore)
重置 state
使用选项式 API 时,你可以通过调用 store 的 $reset() 方法将 state 重置为初始值。
userStore.$reset()
console.log(userStore)
在 Setup Stores 中,您需要创建自己的 $reset() 方法:
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function $reset() {
count.value = 0
}
return { count, $reset }
})
修改state值
直接修改
userStore.username = "xiaohei"
批量修改
const userStore =useUserStore()
userStore.$patch({
username:'xiaoc123456',
age:100,
})
借助action
修改(action
中可以编写一些业务逻辑)
import { defineStore } from 'pinia'
export const useUserStore = defineStore("user",{
state(){
return{
username : "xiaoc", //属性都将自动推断出它们的类型
age : 25,
poclist:[{ id: "dasdasdad01", title: "禅道 12.4.2 后台任意文件上传漏洞", content: "禅道 <= 12.4.2版本" },
{ id: "dasdasdad02", title: "Rails sprockets 任意文件读取漏洞", content: "Sprockets < 3.7.1" },
{ id: "dasdasdad03", title: "Rails sprockets 任意文件读取漏洞", content: "Sprockets < 3.7.1" },
{ id: "dasdasdad04", title: "HiKVISION 综合安防管理平台 report 任意文件上传漏洞", content: "HiKVISION 综合安防管理平台" }]
}
},
actions:{
updateusername(){
this.username ="这是通过action修改的名字"
}
}
组件中调用action
即可
// 使用countStore
const countStore = useCountStore()
// 调用对应action
countStore.incrementOdd(n.value)
storeToRefs
通过解构获取数据,会提示获取到的数据是常数,而不是响应式数据
const {username,age,poclist} =userStore
function changeUsername(){
ager += 1
}
需要使用storeToRefs
const {username,age,poclist} =storeToRefs(userStore)
function changeUsername(){
age.value += 1
}
监听state
类似于 Vuex 的 subscribe 方法,你可以通过 store 的 $subscribe() 方法侦听 state 及其变化。比起普通的 watch(),使用 $subscribe() 的好处是 subscriptions 在 patch 后只触发一次 (例如,当使用上面的函数版本时)。
cartStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// 和 cartStore.$id 一样
mutation.storeId // 'cart'
// 只有 mutation.type === 'patch object'的情况下才可用
mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state))
})
userStore.$subscribe((mutation,state)=>{
console.log(mutation,state);
})
存储本地会话
function changename(){
userStore.updateusername()
localStorage.setItem('poclist',JSON.stringify(userStore.poclist))
}
Getter
Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数:
import { defineStore } from 'pinia'
export const useUserStore = defineStore("user",{
state(){
return{
username : "xiaoc", //属性都将自动推断出它们的类型
age : 25,
poclist:[{ id: "dasdasdad01", title: "禅道 12.4.2 后台任意文件上传漏洞", content: "禅道 <= 12.4.2版本" },
{ id: "dasdasdad02", title: "Rails sprockets 任意文件读取漏洞", content: "Sprockets < 3.7.1" },
{ id: "dasdasdad03", title: "Rails sprockets 任意文件读取漏洞", content: "Sprockets < 3.7.1" },
{ id: "dasdasdad04", title: "HiKVISION 综合安防管理平台 report 任意文件上传漏洞", content: "HiKVISION 综合安防管理平台" }]
}
},
getters:{
doubleAge:(state)=>state.age*2
},
actions:{
updateusername(){
this.username ="这是通过action修改的名字"
}
}
})
使用其他 getter
我们也可以通过 this 访问到整个 store 实例,但(在 TypeScript 中)必须定义返回类型。这是为了避免 TypeScript 的已知缺陷,不过这不影响用箭头函数定义的 getter,也不会影响不使用 this 的 getter。
读取数据
可以直接访问 store 实例上的 getter
getters:{
doubleAge:(state)=>state.age*2,
changeDoubleAge():number{
return this.doubleAge*4
}
},
Action
Action 相当于组件中的 method。它们可以通过 defineStore() 中的 actions 属性来定义,并且它们也是定义业务逻辑的完美选择。
export const useCounterStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})