Vue3-Pinia(小菠萝)使用详解

写在前面

一分钟速览 Pinia 简介

  • 是什么: Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。类似 Vuex
  • 开发工具支持: 不管是 Vue 2 还是 Vue 3,支持 Vue devtools 钩子的 Pinia 都能给你更好的开发体验。
  • 极致轻量化: inia 大小只有 1kb 左右,你甚至可能忘记它的存在!
  • 类型推断: 让我们可以享受类型推断的红利,即使在 JavaScript 中亦可以提供自动补全功能
  • 发展: Vue官方已决定将其作为新的推荐方案来代替 Vuex

Pinia对比 Vuex

  • 更好的 TypeScript支持: 无需要创建自定义的复杂包装器来支持 TypeScript,一切都可标注类型,API 的设计方式是尽可能地利用 TS 类型推理。
  • 抛弃 mutation: mutation 已被弃用。它们经常被认为是极其冗余的。它们初衷是带来 devtools 的集成方案,但这已不再是一个问题了。
  • 更简单好用: 与 Vuex 相比,Pinia 不仅提供了一个更简单的 API,也提供了符合组合式 API 风格的 API,最重要的是,搭配 TypeScript 一起使用时有非常可靠的类型推断支持。

Pinia 官网:https://pinia.vuejs.org/zh/index.html


一、安装

1.1 命令窗口安装
npm install pinia
// or
yarn add pinia
1.2 在 main.ts 中引入
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 导入 pinia
import { createPinia } from 'pinia'
// 创建 pinia 实例
const pinia = createPinia()
// 挂载到根实例
const app = createApp(App)
app.use(pinia)

app.mount('#app')

二、使用 Pinia数据

2.1 创建仓库

在 src > store > index.js 中写入如下代码

import { defineStore } from "pinia"

// 1.定义并导出容易
// 参数1:容器的 ID,必须唯一,将来 Pinia 会把所有的容器挂载到跟容器
export const useMainStore = defineStore('main', {
  /**
   * 类似于组件的 data,用来存储全局状态
   */
  state: () => {
    return {
    }
  },

  /**
   * 类似组件的  computed,用来封装计算属性,有缓存功能
   */
  getters: {

  },
  
  /**
   * 类似组件的 methods,封装业务逻辑,修改 state
   */
  actions: {},
})
2.2 假如 state 中就一个数据
state: () => {
    return {
      count:100
    }
  },

在 vue 文件中直接使用即可

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

const mainStore = useMainStore()
</script>

<template>
  <div>
    // 直接使用
    <h1>{{ mainStore.count }}</h1>
  </div>
</template>
2.3 假如 state 中有多个数据
  state: () => {
    return {
      count: 100,
      name:'张三'
    }
  },

需要引入 storeToRefs,将结构的数据转为响应式的数据

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

const mainStore = useMainStore()
// 直接结构得到的并非响应式数据
// const { count , name} = mainStore

// 用 pinia 的 storeToRefs包裹后,结构出来就是响应式的数据
const { count , name} = storeToRefs(mainStore)
const handleChange = () => {
  count.value+=20
}
</script>

<template>
  <div>
    <h1>{{ name }}</h1>
    <h1>{{ count }}</h1>
    <button @click="handleChange">+20</button>
  </div>
</template>

三、状态更新和 Actions

注意点:

1、建议还是通过 $patch,批量更新对性能更友好
2、actions 中不能使用箭头函数定义,因为箭头函数本身并无 this

3.1 修改和逻辑相对简单时,在Vue 文件中直接修改即可
const handleChange = () => {
  // 方式一:最简单的方式就是这样但不建议
  mainStore.count++

  // 方式二:批量更新方式: $patch 一个函数
  mainStore.$patch(state=>{
    state.count++,
    state.name = 'jack'
  })
}
3.3 逻辑较多时,可以封装到 actions 中做处理

先在 actions 中定义 (文件位置:/ src / store / index.ts)

 actions: {
   // 注意:此处定义不能使用箭头函数,因为箭头函数本身并无 this
   changeState(){
     // 相当于此时的 actions是 Vue模板中的 methos,state是 vue模板中的data
     this.count += 2
     this.name = '李四'
     this.arr.push(10)
   }
 },

然后再 vue 文件的方法中调用即可

const handleChange = () => {
  // 方式三:将逻辑复杂的封装到 actions 中处理
  mainStore.changeState()
}
3.4 自定义参数,传到 actions 中使用
// 在 Vue 文件中调用时传入参数
const handleChange = () => {
  // 传入参数10
  mainStore.changeState(10)
}

// 在 actions 中接受参数并使用
  actions: {
    // 注意:此处定义不能使用箭头函数,因为箭头函数本身并无 this
    changeState(step:number){
     // 相当于此时的 actions是 Vue模板中的 methos,state是 vue模板中的data
      this.count += step
    }
  },

四、Getters 的使用

gettes 中定义的方法有缓存,如果数据没变,多次调用也仅会执行一次

先在 getters 中定义

  /**
   * 类似组件的  computed,用来封装计算属性,有缓存功能
   */
  getters: {
    // 写法一:函数可以接收一个可选参数:state 状态对象
    count20(state) {
      console.log("调用了count20")
      return state.count + 20
    },

    // 写法二:不用 state,则必须手动指定返回值的类型,否则类型推导不出来
    count30() : number{
      console.log("调用了count30")
      return this.count + 30
    },

    // 写法三:接收 state 但是不用,麻瓜写法不建议
    count40(state){
      console.log("调用了count40")
      return this.count + 40
    }
  },

Vue 文件中直接使用

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

const mainStore = useMainStore()
</script>

<template>
  <div>
    // 直接使用即可 -- 调用三次也仅会执行一次
    <p>{{ mainStore.count20 }}</p>
    <p>{{ mainStore.count20 }}</p>
    <p>{{ mainStore.count20 }}</p>
  </div>
</template>

你可能感兴趣的:(笔记,vue.js,javascript,前端)