Pinia快速入门

本文详细介绍了Pinia在Vue中的使用,包括创建项目、安装、挂载、基础功能如getter、action以及异步操作,还有storeToRefs的使用和Pinia的调试。
摘要由CSDN通过智能技术生成


前言

Pinia和Vuex有很多相似之处,它们都是用于实现状态管理的插件。但是,Pinia相对于Vuex来说,更加轻量,并且提供了更多的功能,例如支持异步状态更新、更好的调试能力等🍍🥭🍎。


一、🍍什么是Pinia

Pinia是Vue的专属的最新状态管理库,是Vuex状态管理工具的替代品

image-20230827103810137

优势:

  1. 提供了更加简单的API(去掉了mutation)
  2. 提供符合组合式风格的API(和Vue3新语法统一)
  3. 去掉modules的概念,每一个store都是独立的模块
  4. 搭配TypeScript一起使用提供可靠的类型推断

1. 创建Vue空项目

npm init vue@latest

image-20230827113603688

使用VScode打开项目,并安装依赖,然后运行项目

cd vue-pinia
npm install
npm run dev

项目创建完成

image-20230827113823271

2. 安装Pinia

npm install pinia

image-20230827114052358

3. 将Pinia挂载到vue项目中

main.js

import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

//1. 导入createPinia
import {createPinia} from 'pinia'

//2. 执行方法得到实例
const pinia=createPinia()

//3. 将pinia实例加入到app中
createApp(App).use(pinia).mount('#app')

Pinia在vue中是以插件的形式存在。

二、🥞Pinia基础使用

1. 官网案例

核心步骤:

  1. 定义Store

    stores/counter.js

    import { defineStore } from 'pinia'
    import { ref } from 'vue'
    export const useCounterStore = defineStore('counter', () => {
        //数据(state)
        const count = ref(0)
    
        //定义修改数据的方法(action 同步+异步)
        const increment = () => {
            count.value++
        }
    
        //以对象的形式返回
        return { count, increment }
    })
    

    官方提示:

    1. 你可以对 defineStore()的返回值进行任意命名,但最好使用 store 的名字,同时以 use开头且以 Store结尾。(比如 useUserStore,useCartStore,useProductStore)

    2. 第一个参数是你的应用中 Store 的唯一 ID。

    3. defineStore() 的第二个参数可接受两类值:Setup 函数或 Option 对象。

  2. 在组件中使用store

    App.vue

    <script setup>
      //1. 引入方法
      import {useCounterStore} from '@/stores/counter'
    
      //2. 执行方法得到store实例
      const counterStore=useCounterStore()
      console.log(counterStore);
    </script>
    
    <template>
      <button @click="counterStore.increment">{{counterStore.count}}</button>
    </template>
    
    

    image-20230827145405241

2. getter实现

Pinia中的getters直接使用computed函数进行模拟。

Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore() 中的 getters属性来定义它们。推荐使用箭头函数,并且它将接收 state作为第一个参数.

stores/counter.js

import {defineStore} from 'pinia'
import {computed, ref} from 'vue'

export const useCounterStore = defineStore('counter', () => {
    //数据(state)

    const count = ref(0)

    //定义修改数据的方法
    const increment = () => {
        count.value++
    }

    //定义getter
    const doubleCount = computed(() => count.value * 2)

    //以对象的形式返回
    return {count, increment, doubleCount}
})

App.vue

<script setup>
  //引入方法
  import {useCounterStore} from '@/stores/counter'

  //执行方法得到store实例
  const counterStore=useCounterStore()
  console.log(counterStore);
</script>

<template>
  <button @click="counterStore.increment">{{counterStore.count}}</button><br>

  <div>这是刚刚定义的doubleCount:{{ counterStore.doubleCount}}</div>

</template>

image-20230827150956868

大多数时候,getter 仅依赖 state,不过,有时它们也可能会使用其他 getter。因此,即使在使用常规函数定义 getter 时,我们也可以通过 this访问到整个 store 实例,但(在 TypeScript 中)必须定义返回类型。这是为了避免 TypeScript 的已知缺陷,不过这不影响用箭头函数定义的 getter,也不会影响不使用 this 的 getter。

3. action如何异步实现

action中实现异步和组件中定义数据和方法的风格完全一致

先安装axios

npm install axios

image-20230827152057958

stores/counter.js

此处创建了一个异步的action用来请求一个列表数据,和一个响应式的列表用来存储数据(我把之前的内容删掉了,以免产生误导,还是原来的两个文件)

import {defineStore} from 'pinia'
import {computed, ref} from 'vue'
import axios from "axios";

export const useCounterStore = defineStore('counter', () => {
    //定义一个异步action
    const list = ref([])
    const getList = async () => {

        //此接口已经失效,无法发起请求,只能模拟一下数据,意思意思
        // const response = await axios.get("http://geek.itheima.net/y1_0/channels")

        // response.data.data.channels返回的就是一个列表,下面用模拟数据演示
        // list.value = response.data.data.channels
        list.value = ['模拟数据1', '模拟数据2', '模拟数据3', '模拟数据4', '模拟数据5', '模拟数据6']
    }
    //以对象的形式返回
    return {list, getList}
})

App.vue

<script setup>

import {useCounterStore} from '@/stores/counter'
import {onMounted} from "vue";

const counterStore = useCounterStore()
console.log(counterStore);

onMounted(() => {
  counterStore.getList()
})
</script>

<template>
  <ul>
    <li v-for="item in counterStore.list" >{{item}}</li>
  </ul>
</template>

image-20230827154847257

注意:此处把axios的请求注释掉完全是无奈之举,不注释掉会报错,导致模拟数据也无法渲染

4. storeToRefs函数

使用storeToRefs函数可以辅助保持数据 (state + getter) 的响应式解构

错误示范:直接解构赋值(响应式丢失)

<script setup>
import {useCounterStore} from '@/stores/counter'

const counterStore = useCounterStore()

//直接解构赋值
const {count, doubleCount} = useCounterStore()

</script>

<template>
  <button @click="counterStore.increment">{{ count }}</button>
  <br>
  <div>这是刚刚定义的doubleCount:{{ doubleCount }}</div>
</template>

App.vue

image-20230827161942227

加上storeToRefs()

<script setup>

import {useCounterStore} from '@/stores/counter'
//引入storeToRefs
import {storeToRefs} from "pinia";

const counterStore = useCounterStore()
//方法包裹(保持响应式更新)
const {count, doubleCount} =storeToRefs(useCounterStore()) 

</script>

<template>
  <button @click="counterStore.increment">{{ count }}</button>
  <br>
  <div>这是刚刚定义的doubleCount:{{ doubleCount }}</div>
</template>

数据正常响应

image-20230827162602040

打印前后两次解构出来的值,使用过storeToRefs后解构出来的才是响应式的数据

image-20230827163559563

注意:storeToRefs只负责数据的解构,方法无法通过其解构,如果要解构方法,只需要从原本的store对象中解构即可

const {increment} =counterStore

5. 调试Pinia

image-20230827164454214

总结

本文很简单的介绍了Pinia的使用,对于需要快速开发但又从未接触过Pinia的朋友极其友好,如果喜欢的话望收藏,点赞,有不足之处还望能够在评论区指出。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

笑的像个child

好人一生平安,先磕为敬

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

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

打赏作者

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

抵扣说明:

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

余额充值