Vue3项目中Pinia使用详解

开篇

本文的目的是创建一个使用typescript的vue3项目,并使用pinia来管理状态。

详细步骤

创建项目

  • 创建vue3项目,并使用vite作为打包工具
npm create vite@latest vue3_pinia
// 选择vue,随后选择typesript
  • 进入项目,并按照依赖包
cd vue3_pinia
npm i
  • 安装pinia
npm i pinia

配置Pinia

  • 在src下新建stores文件夹,并在stores文件夹下新建index.ts文件
  • 在src/main.ts中引入pinia,并进行配置
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 引入pinia
import { createPinia } from 'pinia'

// 创建pinia实例
const pinia = createPinia()

createApp(App).use(pinia).mount('#app')
  • 在store/index.ts中写入一些基本的数据用于测试
import { defineStore } from "pinia";

export const useExampleStore = defineStore('example', {
    state: () => {
        return {
            count: 3
        }
    },

    getters: {
        // 判断是否是偶数
        isEven: state => state.count % 2 === 0,
        // 求平方
        isSquare: state => state.count * state.count
    },
    actions: {
        increment() {
            this.count++
        }
    }
})

读取Store中的数据

  • 在src/components下新建PiniaDemo.vue组件,并引入useExampleStore 得到store实例,从而渲染stores中的数据
<script setup lang="ts">
import { useExampleStore } from '../stores/index';

const store = useExampleStore();
</script>

<template>
    <div>
        <p>Count: {{ store.count }}</p>
        <p>isEven: {{ store.isEven }}</p>
        <p>Square: {{ store.isSquare }}</p>
        <button @click="store.increment">+1</button>
    </div>
</template>

<style scoped>
    div {
        border: 1px solid gray;
        width: 200px;
        height: 200px;
    }
</style>
  • 在App.vue中,引入PiniaDemo.vue组件,此时,页面上的效果如下:
    在这里插入图片描述

  • 此时点击按钮,发现已经生效了的
    在这里插入图片描述

  • 肯定你也发现了,渲染的还是,都是store.xxx,这非常不方便!所以,在PiniaDemo.vue中使用解构的方式来获取这些值,并渲染

<script setup lang="ts">
import { useExampleStore } from '../stores/index';
import { storeToRefs } from 'pinia'

const store = useExampleStore();

// 注意,解构的时候,要使用这个方法,不然解构出来的值就不是响应式了
const { count, isEven, isSquare } = storeToRefs(store);
const { increment } = store;
</script>

<template>
    <div>
        <p>Count: {{ count }}</p>
        <p>isEven: {{ isEven }}</p>
        <p>Square: {{ isSquare }}</p>
        <button @click="increment">+1</button>
    </div>
</template>

<style scoped>
    div {
        border: 1px solid gray;
        width: 200px;
        height: 200px;
    }
</style>
  • 当然,我们也可以一次性修改多条state中的数据, 现在在index.ts的state中,新增一个数据
    state: () => {
        return {
            count: 3,
            pet: 'cat'
        }
    },
  • 在PiniaDemo.vue中增加change按钮,并一次性修改count和pet两个数据(注意:$patch的两种用法都列出来啦!)
<script setup lang="ts">
import { useExampleStore } from '../stores/index';
import { storeToRefs } from 'pinia'

const store = useExampleStore();

// 注意,解构的时候,要使用这个方法,不然解构出来的值就不是响应式了
const { count, isEven, isSquare, pet } = storeToRefs(store);
const { increment } = store;

// $patch的第一种用法
// const patchClickEvent = () => {
//     store.$patch(store => {
//         store.count += 2;
//         store.pet = store.pet === 'cat' ? 'dog' : 'cat'
//     })
// }

//$patch的第2种用法
const patchClickEvent = () => {
    store.$patch({
        count: store.count+2,
        pet: store.pet === 'cat' ? 'dog' : 'cat'
    })
}
</script>

<template>
    <div>
        <p>Count: {{ count }}</p>
        <p>isEven: {{ isEven }}</p>
        <p>Square: {{ isSquare }}</p>
        <p>pet: {{  pet }}</p>
        <button @click="increment">+1</button>
        <!-- 其他改变数据的方式之$patch, 可一次修改多条-->
         <button @click="patchClickEvent">change</button>
    </div>
</template>
  • 点击按钮,此时效果如下

在这里插入图片描述

不同store文件间的通信

  • 在stores下新建pet.ts文件,并构建基本的代码,可以看到,这里代码比较简单,只定义了一个数组类型的petList数据
import { defineStore } from 'pinia'

export const usePetStore = defineStore('pet', {
    state: () => {
        return {
            petList: ['cat', 'dog', 'rabbit']
        }
    }
})
  • 在stores/index.ts中引入usePetStore,并定义一个getPetList方法,获取petList的值(此处为了方便,我直接给出index.ts所有的代码
import { defineStore } from "pinia";
import { usePetStore } from './pet'

export const useExampleStore = defineStore('example', {
    state: () => {
        return {
            count: 3,
            pet: 'cat'
        }
    },

    getters: {
        // 判断是否是偶数
        isEven: state => state.count % 2 === 0,
        // 求平方
        isSquare: state => state.count * state.count
    },
    actions: {
        increment() {
            this.count++
        },

        getPetList() {
            return usePetStore().petList
        }
    }
})
  • 在PiniaDemo.vue中使用getPetList()方法渲染petList数组
<p>petList: {{ getPetList() }}</p>
...
const { increment, getPetList } = store;
  • 此时,效果如下
    在这里插入图片描述

以上便是Pinia的一些使用方式了,希望能对您起到抛砖引玉的参考作用。

相关推荐

  1. Vue 项目使用 Pinia 状态管理详细教程

    2024-06-14 18:02:04       39 阅读
  2. vue3使用pinia

    2024-06-14 18:02:04       13 阅读
  3. Vue3 基础知识》Pinia 02 之 项目VuexPinia

    2024-06-14 18:02:04       8 阅读
  4. PiniaVue 3项目的应用

    2024-06-14 18:02:04       13 阅读
  5. vue3在router使用pinia报错解决

    2024-06-14 18:02:04       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-14 18:02:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-14 18:02:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-14 18:02:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-14 18:02:04       20 阅读

热门阅读

  1. 0074__Microsoft Typography documentation

    2024-06-14 18:02:04       5 阅读
  2. 1111111222

    2024-06-14 18:02:04       7 阅读
  3. xml数据解析

    2024-06-14 18:02:04       6 阅读
  4. Interview preparation--案例加密后数据的模糊查询

    2024-06-14 18:02:04       10 阅读
  5. ORACLE中ROWNUM的机制和注意细节(避坑

    2024-06-14 18:02:04       7 阅读
  6. Android10 动态修改开机动画(一)新增分区

    2024-06-14 18:02:04       8 阅读
  7. python+selenium做ui自动化测试用法必会

    2024-06-14 18:02:04       9 阅读
  8. 网格大师输出fbx可以合并成单文件吗?

    2024-06-14 18:02:04       6 阅读