pinia的使用
安装
bash
yarn add pinia
# 或者使用 npm
npm install pinia
# 或者使用 pnpm
pnpm add pinia
基本用法
vue3项目入口main.js文件配置pinia:
JavaScript
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './style.css'
import App from './App.vue'
const store=createPinia()
let app=createApp(App)
app.use(store)
app.mount('#app')
在src文件夹下创建store文件夹,并在此文件夹下创建index.ts文件:
typescript
import { defineStore } from 'pinia'
export const useTestStore=defineStore('Test',{
state:()=>{
return{
current:1,
name:'rarrot'
}
},
// computed 修饰值
getters:{
},
// methods 可以做同步异步,提交state
actions:{
setCurrent(num:number){
// this是由定义好的store实例调用的,箭头函数只会保存当前作用域的this
this.current=num
}
}
})
在App.vue进行使用:
vue
<template>
<div>
pinia:{{ test.age }}--{{ test.name }}
<br>
<button @click="change">change</button>
</div>
</template>
<script setup lang='ts'>
// import { ref, reactive } from 'vue'
import { useTestStore } from './store'
const test = useTestStore()
// 修改值的方式
// 1.直接修改test.age++
// 2.用test.$patch({ age:888 })进行修改
// 3.用函数的写法:test.$patch((state)=>{ state.age=999 }) 推荐
// 4.整个对象进行修改test.$state={ age:1000,name:'rarrot' }
// 5.在store里边的actions里面定义一个函数,然后直接调用test.setage(123)
function change(){
test.setAge(123)
}
</script>
<style scoped></style>
storeToRefs源码详解
对pinia进行解构会失去响应式,但是通过storeToRefs可以将一个存储对象(store)转换为一组响应式的引用(refs),使其重新具备响应式。
JavaScript
/**
* 创建一个对象包含所有的state, getters, and plugin-added
* state 属性 of the store. 类似于 `toRefs()` 但是是特别地
* 专为 Pinia stores 设计,所以方法和非响应式属性完全忽略
*
* @param store - store to extract the refs from
*/
function storeToRefs(store) {
// See https://github.com/vuejs/pinia/issues/852
// 使用toRefs()更容易,虽然它包含更多的东西.
// 判断是vue2就直接使用toRefs
if (isVue2) {
// @ts-expect-error: toRefs include methods and others
return toRefs(store);
}
else {
// 将ref响应式对象转换为原始对象
console.log(store)
store = toRaw(store);
console.log(store)
const refs = {};
// 遍历store,判断是否为响应式ref或reactive,是就通过toRef转换为引用
// 并添加至refs中,遍历完后返回
for (const key in store) {
const value = store[key];
if (isRef(value) || isReactive(value)) {
// @ts-expect-error: the key is state or getter
refs[key] =
// ---
toRef(store, key);
}
}
return refs;
}
}
actions的同步异步使用
同步调用
./store/index.ts
typescript
import { defineStore } from 'pinia'
type User={
name:string,
age:number
}
let result:User={
name:'鸡',
age:999
}
export const useTestStore=defineStore('test',{
state:()=>{
return{
user:<User>{},
name:'鹅'
}
},
// computed 修饰值
getters:{
},
// methods 可以做同步异步,提交state
actions:{
setUser(){
this.user=result
}
}
})
./App.vue
vue
<template>
<div>
pinia:{{ test.user }}
<br/>
pinia:{{ test.name }}
<button @click="change">change</button>
</div>
</template>
<script setup lang='ts'>
// import { ref, reactive } from 'vue'
import { useTestStore } from './store';
const test = useTestStore()
function change() {
test.setUser()
}
</script>
<style scoped></style>
异步调用
typescript
import { defineStore } from 'pinia'
type User = {
name: string,
age: number
}
const Login = (): Promise<User> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
name: '鸡',
age: 999
})
}, 2000);
})
}
export const useTestStore = defineStore('test', {
state: () => {
return {
user: <User>{},
name:'鹅'
}
},
// computed 修饰值
getters: {
},
// methods 可以做同步异步,提交state
actions: {
async setUser() {
const result = await Login()
this.user = result
this.setName('鸭')
},
setName(name:string){
this.name=name
}
}
})
getters用法
在原来代码基础上添加以下代码
./store/index.ts
typescript
// computed 修饰值
getters: {
newName():string{
return `${this.name}--${this.getAge}`
},
getAge():number{
return this.user.age
}
},
./App.vue
vue
<p>getter:{{ test.newName}}</p>
pinia的API
vue
<template>
<div>
pinia:{{ test.user }}
<br />
pinia:{{ test.name }}
<br />
<p>getter:{{ test.newName }}</p>
<button @click="change">change</button>
<br /><br />
<button @click="reset">reset</button>
</div>
</template>
<script setup lang='ts'>
// import { ref, reactive } from 'vue'
import { useTestStore } from './store';
const test = useTestStore()
test.$subscribe((args, state) => {
// 包含新值旧值
console.log("🚀 args1", args)
// 包含store里面state的数据
console.log("🚀 state", state)
})
test.$onAction((args) => {
// 后输出
args.after(() => {
console.log('after')
})
console.log("🚀 args2", args)
}, true)
function change() {
test.setUser()
}
const reset = () => {
// 将修改的值进行恢复
test.$reset()
}
</script>
<style scoped></style>