Vue使用Pinia实现状态管理

Pinia初始化

  • 创建VUE3项目
npm init vite @latest
  • 安装Pinia
npm install pinia
  • Pinia挂载到vue实例

    main.ts

import {createApp} from 'vue'
import App from './App.vue'
import {createPinia} from "pinia";

createApp(App)
    .use(createPinia())
    .mount('#app')
  • src目录下新建story/index.ts并配置
import {defineStore} from "pinia";

export const useMainStore = defineStore('main', {
    state: () => {
        return {}
    },

    getters: {},

    actions: {}
})

参数说明:
defineStore(容器唯一标识(会将其挂载到根容器),参数选项)
state:存储全局状态
getters:封装计算属性 具有缓存功能
actions:封装业务逻辑 修改state

测试Pinia是否可用

  • 配置index.ts
import {defineStore} from "pinia";

export const useMainStore = defineStore('main', {
    state: () => {
        return {
            testPinia: '欢迎使用Pinia'
        }
    },

    getters: {},

    actions: {}
})
  • 编写TestPinia.vue

<template>

</template>

<script setup lang="ts">
import {useMainStore} from "./";

const mainStory = useMainStore()

console.log(mainStory.testPinia)

</script>

<style scoped>

</style>
  • 编写App.vue

<script setup lang='ts'>
import TestPinia from './components/TestPinia.vue';
</script>

<template>
  <TestPinia/>
</template>

<style>

</style>
  • 测试结果

在这里插入图片描述

通过解构访问Pinia数据

为什么要解构使用?
由于在模板中使用pinia数据时,需要通过容器对象来拿到数据十分繁琐
所以将数据通过解构的方式使其只需要通过参数名就能直接拿到对应的值

  • 未解构前
    TestPinia.vue

<template>
  <h1>未解构</h1>
  <p>显示内容1:{{ mainStory.testPinia1 }}</p>
  <p>显示内容2:{{ mainStory.testPinia2 }}</p>
  <hr/>
  <h1>解构后</h1>
  <p>显示内容1:{{ testPinia1 }}</p>
  <p>显示内容2:{{ testPinia2 }}</p>
  <hr/>
  <button @click="updateData">修改内容</button>
</template>

<script setup lang="ts">
import {useMainStore} from '../story';

const mainStory = useMainStore()

console.log(mainStory.testPinia)

/*解构语句*/
const {testPinia1, testPinia2} = mainStory

const updateData = () => {
  mainStory.testPinia1 = '修改成功';
}

</script>

<style scoped>

</style>

index.ts

import {defineStore} from "pinia";

export const useMainStore = defineStore('main', {
    state: () => {
        return {
            testPinia: '欢迎使用Pinia',
            testPinia1: '欢迎使用Pinia1',
            testPinia2: '欢迎使用Pinia2'
        }
    },

    getters: {},

    actions: {}
})

结果:
在这里插入图片描述

存在问题:
使用解构的方式拿到的数据不是响应式的,而是一次性的
也就是当数据发生改变时不会自动改变
例如:当点击修改后,只有未解构的内容发改变,而结构后的不会改变

在这里插入图片描述

如何解决解构内容不更新问题?
使用Pinia官方APIstoreToRefs解决
storeToRefs:
将结构出来的数据用ref来代理响应式


<template>
  <h1>未解构</h1>
  <p>显示内容1:{{ mainStory.testPinia1 }}</p>
  <p>显示内容2:{{ mainStory.testPinia2 }}</p>
  <hr/>
  <h1>解构后</h1>
  <p>显示内容1:{{ testPinia1 }}</p>
  <p>显示内容2:{{ testPinia2 }}</p>
  <hr/>
  <button @click="updateData">修改内容</button>
</template>

<script setup lang="ts">
import {useMainStore} from '../story';
import {storeToRefs} from "pinia";

const mainStory = useMainStore()

/*修改后的解构语句*/
const {testPinia1, testPinia2} = storeToRefs(mainStory)

const updateData = () => {
  mainStory.testPinia1 = '修改成功';
}

</script>

<style scoped>

</style>

此时在单击修改按钮时,都发生了改变:
在这里插入图片描述

状态更新及action

  • 方式一:直接赋值更新
mainStory.testPinia1 = '已更新';
  • 方式二:使用$patch更新多个数据 批量更新
 mainStory.$patch({
    testPinia1: '已更新1',
    testPinia2: '已更新2',
})
  • 方法三:直接拿到 state进行修改 批量
  mainStory.$patch(state => {
    state.testArr.push(4)
})
  • 方式四:封装到action中使用(可以手动传参)
import {defineStore} from "pinia";

export const useMainStore = defineStore('main', {
    state: () => {
        return {
            testPinia: '欢迎使用Pinia',
            testPinia1: '欢迎使用Pinia1',
            testPinia2: '欢迎使用Pinia2',
            testArr: [1, 2, 3, 4]
        }
    },

    getters: {},

    actions: {
        changeState(val: string) {
            this.testPinia1 = '通过action修改成功';
        }, changeState2(val: string) {
            this.testPinia1 = val;
        }
    }
})
  mainStory.changeState();
mainStory.changeState2("你好");

在这里插入图片描述

注意:
在使用action定义函数时,不能使用箭头函数
箭头函数绑定的外部this 而在函数体中无法使用当前的this

getters使用

getters是具有缓存功能的,在代码中连续实际只会执行一次
参数中的state是一个可选参数

    getters: {
    /*state:可选参数*/
    addOne(state)
    {
        console.log("addOne被调用");
        return state.count + 1;
    }
}

<template>
  <p>{{ mainStory.addOne }}</p>
  <p>{{ mainStory.addOne }}</p>
  <p>{{ mainStory.addOne }}</p>
</template>

<script setup lang="ts">
import {useMainStore} from '../story';
import {storeToRefs} from "pinia";

const mainStory = useMainStore()

const {testPinia1, testPinia2, testArr, count} = storeToRefs(mainStory)


</script>

在这里插入图片描述
源码地址:Vue3-Pinia

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_何同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值