Vue pinia 基础使用

55 阅读2分钟

一、环境搭建

1.1 安装

npm i pinia

image.png

1.2 引用

image.png
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia'
const store =createPinia()

export const app =  createApp(App)

app.use(store)
app.mount('#app')

二、简单使用

2.1 初始化

创建枚举类 store-name.ts

export const enum Names {
    TEST = "TEST"
}

创建 store

import {defineStore} from 'pinia'
import {Names} from "./store-name"

export const useTestStore = defineStore(Names.TEST,{
    state:()=>{
        return {
            current:1,
            name:'xyy'
        }
    },
    // 类似于computed,有缓存
    getters:{

    },
    // 类似于 methods,可以做同步、异步、提交
    actions:{

    }
})

2.2 使用

<template>
    {{ Test.current }} --- {{ Test.name }}

</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

</script>

image.png

三、修改 store 值

3.1 直接修改

<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

const change = ()=>{
    Test.current++ 
}

</script>

20231126_164316.gif

3.2 $patch 批量修改

<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

const change = ()=>{
    Test.$patch({
        current:888,
        name:"xyy123"
    })
}

</script>

20231126_164628.gif

3.3 $patch 函数处理

<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

const change = ()=>{
    Test.$patch((state)=>{
        state.current = 999
        state.name = "zhangsan"
    })
}

</script>

20231126_164938.gif

3.4 $state 批量修改

<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

const change = ()=>{
    Test.$state = {
        current:111,
        name:"xyy567"
    }
}

</script>

20231126_165310.gif

3.5 action

在 store 中的action 添加修改逻辑

import {defineStore} from 'pinia'
import {Names} from "./store-name"

export const useTestStore = defineStore(Names.TEST,{
    state:()=>{
        return {
            current:1,
            name:'xyy'
        }
    },
    // 类似于computed,有缓存
    getters:{

    },
    // 类似于 methods,可以做同步、异步、提交
    actions:{
       setCurrent(){
        this.current = 555
       }
    }
})

使用定义好的函数方法

<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

const change = ()=>{
   Test.setCurrent()
}

</script>

20231126_165640.gif

四、 解构 store

4.1 基础使用

<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()

const {current,name} = Test

const change = ()=>{
    
  console.log(current,name)
}

</script>

image.png

4.2 常见问题

注意:pinia解构不具有响应式

20231126_170518.gif

解决策略:使用storeToRefs

image.png
<template>
    {{ Test.current }} --- {{ Test.name }}
    <br>
    <button @click="change">change</button>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"
import {storeToRefs} from 'pinia'

const Test = useTestStore()

const {current,name} = storeToRefs(Test)

const change = ()=>{
  Test.current++
  console.log(current,name)
}

</script>

20231126_170849.gif

五、actions

5.1 简单使用

在 store 中的 actions 中为 user 赋值

import {defineStore} from 'pinia'
import {Names} from "./store-name"

type User = {
    name:string,
    age:number
}

let result:User = {
    name:'xyy',
    age:23
}

export const useTestStore = defineStore(Names.TEST,{
    state:()=>{
        return {
            user:<User>{},
            name:''
        }
    },
    // 类似于computed,有缓存
    getters:{

    },
    // 类似于 methods,可以做同步、异步、提交
    actions:{
       setUser(){
        this.user = result
       }
    }
})

调用初始化方法

<template>
    {{ Test }}
    <br>
    <button @click="change">change</button>
    <br>
</template>

<script setup lang='ts'>
import {useTestStore} from "./store"

const Test = useTestStore()


const change = ()=>{
  Test.setUser()
}

</script>

效果如下:

20231126_172309.gif

5.2 调用异步方法

import {defineStore} from 'pinia'
import {Names} from "./store-name"

type User = {
    name:string,
    age:number
}

let result:User = {
    name:'xyy',
    age:23
}

const login = ():Promise<User>=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve({
                name:'zhangsan',
                age:33
            })
        },2000)
    })
}

export const useTestStore = defineStore(Names.TEST,{
    state:()=>{
        return {
            user:<User>{},
            name:''
        }
    },
    // 类似于computed,有缓存
    getters:{

    },
    // 类似于 methods,可以做同步、异步、提交
    actions:{
       async setUser(){
         this.user = await login()
       }
    }
})
image.png 20231126_172807.gif

六、getter

6.1 简单使用

定义 getter 内容

image.png

获取 getter 内容

image.png

image.png

getters 也可以调用同类方法

image.png

20231126_174152.gif

七、api调用

7.1 $reset

作用:重置 store 到他的初始值

image.png 20231126_192604.gif

7.1 $subscribe

作用:监听器,观察的store有变化时,就会走这个函数

image.png

20231126_193101.gif

7.2 $onAction

监听 action 中方法

image.png image.png

此外,还接受一个参数 true,作用为当组件销毁之后,还继续监听这个事件

image.png

八、pinia 持久化插件

8.1 现有问题

当页面刷新后,pinia的状态都会丢失

20231126_194048.gif

8.2 解决过程

在main.ts中,注册自定义store插件

import { createApp,toRaw } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia,PiniaPluginContext } from 'pinia'
const store =createPinia()


const setStorage = (key:string,value:string)=>{
    localStorage.setItem(key,JSON.stringify(value))
}

const getStorage = (key:string)=>{
    return localStorage.getItem(key)?JSON.parse(localStorage.getItem(key) as string) : {}
}

type Options = {
    key?:string
}

const __piniaKey__:string = 'defaultKey'

const piniaPlugin = (options:Options) =>{

    return (context:PiniaPluginContext) =>{
        const {store} = context
        const data = getStorage(`${options?.key??__piniaKey__}-${store.$id}`)
        console.log(data)

        store.$subscribe(()=>{
            console.log(toRaw(store.$state))
            setStorage(`${options?.key??__piniaKey__}-${store.$id}`,toRaw(store.$state))
        })

        return {
            ...data
        }
    }

   
}
store.use(piniaPlugin({
    key:'pinia'
}))

export const app =  createApp(App)

app.use(store)
app.mount('#app')

20231126_200803.gif