Vue全家桶 Pinia状态管理

时间:2023-01-08 07:53:38

Pinia开始于大概2019年,最初是作为一个实验为Vue重新设计状态管理,让它用起来像组合式API,从那时到现在,最初的设计原则依然是相同的,并且目前同时兼容Vue2、Vue3,也并不要求你使用Composition API

所以说,Pinia本质上依然是一个状态管理的库,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样)

1. Pinia和Vuex的对比

Pinia 最初是为了探索Vuex 的下一次迭代会是什么样子,结合了Vuex 5 核心团队讨论中的许多想法,最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以最终决定用Pinia来替代Vuex

与Vuex 相比,Pinia 提供了一个更简单的API,具有更少的仪式,提供了Composition-API 风格的API,最重要的是,在与TypeScript 一起使用时具有可靠的类型推断支持

2. 创建Pinia的Store

安装 pinia 的依赖

$ npm install pinia

创建一个pinia并且将其传递给应用程序

Vue全家桶 Pinia状态管理
创建Pinia的Store

import { createPinia } from "pinia"

const pinia = createPinia()

export default pinia

app.use(pinia)
Vue全家桶 Pinia状态管理

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

import pinia from "./store"
createApp(App).use(pinia).mount('#app')

3. Store 简介与使用

一个Store (如Pinia)是一个实体,它会持有为绑定到你组件树的状态和业务逻辑,也就是保存了全局的状态,你可以在你的应用程序中定义任意数量的Store来管理你的状态

Store有三个核心概念:state、getters、actions,等同于组件的data、computed、methods

一旦store 被实例化,你就可以直接在store *问state、getters 和actions 中定义的任何属性

定义一个Store

我们需要知道Store 是使用defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递,这个name,也称为id,是必要的,Pinia 使用它来将store 连接到devtools

Vue全家桶 Pinia状态管理

import { defineStore } from "pinia";

export const useUser = defineStore("user", {
  state() {
    return {
      name: 'ximingx'
    }
  }
})

使用定义的Store

Store在它被使用之前是不会创建的,我们可以通过调用use函数来使用Store

<script setup>
import { useUser } from '../store/user/index'
const userStore = useUser()
console.log(userStore.name); // ximingx
</script>

注意Store获取到后不能被解构,那么会失去响应式,为了从Store 中提取属性同时保持其响应式,您需要使用storeToRefs()

import { storeToRefs } from 'pinia';
import { useUser } from '../store/user/index'
const userStore = useUser()
const {name: name} = storeToRefs(userStore)
name.value = 'qsx'
console.log(name.value);

4. Pinia核心概念State

state 是store 的核心部分,因为store是用来帮助我们管理状态的,在Pinia 中,状态被定义为返回初始状态的函数

import { defineStore } from "pinia";

export const useUser = defineStore("user", {
  state() {
    return {
      isLogin: false,
      userInfo: {
        nickName: '',
        phone: '',
        email: '',
        lastLoginTime: '',
      }
    }
  }
})

默认情况下,您可以通过store 实例访问状态来直接读取和写入状态

5. Pinia核心概念Getters

Getters相当于Store的计算属性,getters中可以定义接受一个state作为参数的函数

import { defineStore } from "pinia";

export const useUser = defineStore("user", {
  state() {
    return {
      isLogin: false,
      userInfo: {
        nickName: '',
        phone: '',
        email: '',
        lastLoginTime: '',
      }
    }
  },
  getters: {
    getUserName: (state) => `用户名: ${state.userInfo.nickName}`
  }
})

调用

import {useUser} from '../store/user/index'
const userStore = useUser()
console.log(userStore.getUserName);

Getters中访问自己的其他Getters,我们可以通过this来访问到当前store实例的所有其他属性

6. Pinia核心概念Actions

可以使用defineStore() 中的actions 属性定义,并且它们非常适合定义业务逻辑,和getters一样,在action中可以通过this访问整个store实例的所有操作

并且Actions中是支持异步操作的,并且我们可以编写异步函数,在函数中使用await

import { defineStore } from "pinia";

export const useUser = defineStore("user", {
  state() {
    return {
      isLogin: false,
      userInfo: {
        nickName: '',
        phone: '',
        email: '',
        lastLoginTime: '',
      }
    }
  },
  getters: {
    getUserName: (state) => `用户名: ${state.userInfo.nickName}`
  },
  action: {
    async getData() {
      
    }
  }
})