Pinia快速入门

前言

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


一、🍍什么是Pinia

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

优势:

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

1. 创建Vue空项目

shell 复制代码
npm init vue@latest

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

shell 复制代码
cd vue-pinia
npm install
npm run dev

项目创建完成

2. 安装Pinia

shell 复制代码
npm install pinia

3. 将Pinia挂载到vue项目中

main.js

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

    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

    js 复制代码
    <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>

2. getter实现

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

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

stores/counter.js

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

js 复制代码
<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>

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

3. action如何异步实现

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

先安装axios

shell 复制代码
npm install axios

stores/counter.js

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

js 复制代码
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

js 复制代码
<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>

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

4. storeToRefs函数

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

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

js 复制代码
<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

加上storeToRefs()

js 复制代码
<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>

数据正常响应

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

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

js 复制代码
const {increment} =counterStore

5. 调试Pinia

总结

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

相关推荐
Neweee3 分钟前
JavaScript进阶内容详解
前端
大鸡爪4 分钟前
Vue3 组件库实战(五):Icon 图标组件的设计与实现
前端·vue.js
bluceli5 分钟前
前端测试实战指南:构建高质量代码的完整体系
前端·测试
行走的陀螺仪5 分钟前
前端公共库开发保姆级路线:从0到1复刻VueUse官方级架构(pnpm+Turbo+VitePress)
前端·架构
顽固_倔强5 分钟前
深入理解 Vue3 数据绑定实现原理
前端·面试
前端付豪5 分钟前
组件拆分重构 App.vue
前端·架构·代码规范
Wect6 分钟前
React 更新触发原理详解
前端·react.js·面试
cxxcode6 分钟前
Web 帧渲染与 DOM 准备
前端
光影少年7 分钟前
React Hooks的理解?常用的有哪些?
前端·react.js·掘金·金石计划
大鸡爪7 分钟前
Vue3 组件库实战(七):从本地到 NPM:版本管理与自动化发布指南(下)
前端·vue.js