Pinia基本使用---vue3+setup()版本

142 阅读1分钟

如何使用pinia

安装

yarn add pinia
npm install pinia

引入+注册

main.js

import {createPinia} from 'pinia'

const pinia = createPinia()
const app = createApp(App)
app.use(pinia)

定义Store

userStore.ts

import { defineStore } from "pinia";

export const useUserStore = defineStore('user',{
    //类似于vue的data
    state:()=>{
        return {
            name:'xiaofan',
            age:10,
        }
    },
    //类似于vue的computed
    getters:{
        //可选参数:state
        userInfo(state){
            return `${state.name}今年${state.age}岁啦!!!`
        },
        //getter中使用this,必须指明函数的返回值类型,否则类型推断不出来
        nextAge():number{
            return this.age+1
        }
    },
    /**
     * 类似于vue的method
     * 同步、异步都支持
     */
    actions:{
        changeUserName(value:string){
            this.name = value
        },
    }
})

组件中展示数据

UserInfo.vue组件

<script lang="ts">
import { useUserStore } from '../stores/user';
export default{
  setup(){
    const userStore = useUserStore()
    return {
      userStore
    }
  }
}

</script>

<template>
  <div>
    <h1>姓名:{{userStore.name  }}</h1>
    <h1>年龄:{{ userStore.age }}</h1>
    <h2>信息:{{ userStore.userInfo }}</h2>
  </div>
 
</template>

<style >
</style>

image.png

修改数据

1、改单个数据

//template
 <button @click="userStore.age++">长大一岁</button>

2、修改多个数据--$patch--参数对象模式

//template
 <button @click="changeUser">修改多个数据</button>
 
 //script
  const changeUser = ()=>{
        userStore.$patch({
            name:'Jelly',
            age:userStore.age+1
        })
    }

但是,使用这种语法应用某些突变非常困难或代价高昂:任何集合修改(例如,从数组中推送、删除、拼接元素)都需要您创建一个新集合。 正因为如此,$patch 方法也接受一个函数来批量修改集合内部分对象的情况:

3、修改多个数据--$patch--参数函数模式

    //script
    const changeUser1=()=>{
        userStore.$patch((state)=>{
            state.name = "Gillian"
            state.age++
        })
    }

4、用action修改数据

    //template
    <button @click="userStore.changeUserName('Gillian')">修改数据--使用action</button>

解构store中的数据

因为pinia是把state数据做了reactive处理,所以直接解构会失去响应式,要解构出具备响应式的数据,需要借助storeToRefs

    //template
    <h1>直接解构出的数据name----{{ userName }}</h1>
    <h1>stroreToRef解构出的数据-----{{ name }}</h1>
    
    //script
    let {name:userName} =userStore
    let {name,age} = storeToRefs(userStore)

修改数据前 image.png 修改数据后

image.png

重置state为初始化数据---$reset

<button @click="userStore.$reset">重置state中的数据为初始化数据</button>

整个替换state数据---$state

    //script
    const changeState = ()=>{
        userStore.$state={
            name:'Gillian',
            age:18,
        }
    }
    
    //template
    <button @click="changeState">整个修改state的数据</button>

订阅状态---$subscribe

   setup(){
        userStore.$subscribe((mutation,state)=>{

        mutation.type // 'direct' | 'patch object' | 'patch function'
        // 与 cartStore.$id 相同
        mutation.storeId // 'cart'

        console.log(mutation)
        console.log(state)
        
        //state数据变化后,你的操作---例如:更新本地存储
        localStorage.setItem('user'JSON.stringify(state))
        })
    }

image.png

默认情况下,state subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup() 中)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 { detached: true } 作为第二个参数传递给 detach 当前组件的 state subscription

export default {
  setup() {
    const someStore = useSomeStore()

    // 此订阅将在组件卸载后保留
    someStore.$subscribe(callback, { detached: true })

    // ...
  },
}

订阅action及其结果---$onAction

const unsubscribe = userStore.$onAction(
            ({
                name, // action 的名字
                store, // store 实例
                args, // 调用这个 action 的参数
                after, // 在这个 action 执行完毕之后,执行这个函数
                onError, // 在这个 action 抛出异常的时候,执行这个函数
            })=>{
                console.log('store',store)
                const startTime = Date.now()
                // 这将在 `store` 上的操作执行之前触发
                console.log(`Start "${name}" with params [${args.join(', ')}].`)

                // 如果 action 成功并且完全运行后,after 将触发。
                // 它将等待任何返回的 promise
                after((result) => {
                console.log(
                    `Finished "${name}" after ${
                    Date.now() - startTime
                    }ms.\nResult: ${result}.`
                )
                })

                // 如果 action 抛出或返回 Promise.reject ,onError 将触发
                onError((error) => {
                    console.warn(
                        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
                    )
                })
            }
        )
    //手动取消action订阅
    const cancelActionSubscrib = ()=>{
        unsubscribe()
    }

image.png

默认情况下,action* *subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup() 内)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 true 作为第二个参数传递给当前组件的 detach action subscription

export default {
  setup() {
    const someStore = useSomeStore()

    // 此订阅将在组件卸载后保留
    someStore.$onAction(callback, true)

    // ...
  },
}

getter有缓存

    <h2>信息:{{ userStore.userInfo }}</h2>
    <h2>信息:{{ userStore.userInfo }}</h2>
    <h2>信息:{{ userStore.userInfo }}</h2>
    getters:{
        userInfo(state){
            console.log('计算了userInfo')
            return `${state.name}今年${state.age}岁啦!!!`
        },
    },

image.png

只输出了一次