前言
最近学习cloud项目,前端使用到 vue3 + ts 等技术,其中包括 pinia ,从一脸懵到渐渐清晰过程,在此记录一下,若有不足,希望大佬可以指出。
中文官方文档:https://pinia.web3doc.top/
一、什么是 Pinia
Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。实际上,pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名pinia,而没有取名Vuex,所以大家可以直接将pinia比作为Vue3的Vuex。
二、Pinia 和 Vuex 优缺点
Vuex 的优点:
- 支持调试功能,如时间旅行和编辑
- 适用于大型、高复杂度的Vue.js项目
Vuex 的缺点:
- 从 Vue 3 开始,getter 的结果不会像计算属性那样缓存
- Vuex 4有一些与类型安全相关的问题
pinia 的优点:
- 完整的 TypeScript 支持: 与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
- 极其轻巧 (体积约 1KB)
- store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction辅助函数这在 Vuex 中很常见
- 支持多个store
- 支持 Vue devtools、SSR 和 webpack 代码拆分
pinia 的缺点: - 不支持时间旅行和编辑等调试功能
三、何时使用Pinia,何时使用Vuex
- 由于 pinea 是轻量级的,体积很小,它适合于中小型应用。它也适用于低复杂度的Vue.js项目,因为一些调试功能,如时间旅行和编辑仍然不被支持。
- 将 Vuex 用于中小型 Vue.is 项目是过度的,因为它重量级的,对性能降低有很大影响。因此,Vuex 适用于大规模、高复杂度的 Vue.js 项目
四、安装
CMD命令:
npm install pinia
main.ts:
import { createPinia } from 'pinia'app.use(createPinia())
五、核心概念
pinia 常用模版
import { defineStore } from 'pinia'export const userStore = defineStore('userStore', {state: () => ({ // 内容}),actions: { // 内容}})
定义 State
在深入了解核心概念之前,我们需要知道 Store 是使用 defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递:
import { defineStore } from 'pinia'// useStore 可以是 useUser、useCart 之类的任何东西// 第一个参数是应用程序中 store 的唯一 id (userStore)export const useStore = defineStore('userStore', { // other options...})
State
大多数时候,state 是 store 的核心部分。 我们通常从定义应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数(类似 data)。 Pinia 在服务器端和客户端都可以工作。
案例
import { defineStore } from 'pinia'// 唯一 ID: testStoreexport const testStore = defineStore('testStore', { state: () => ({ // 用户信息user: {id: '1',username: 'lanys',password: '123456'} })})
<template> <div> Store: 账号{{user.username}},密码:{{user.password}} </div></template><script setup lang="ts"> // 获取 testStore import { testStore } from '@/store/test'; import { ref,reactive } from 'vue'; const user = reactive({id: '',username: '',password: '' }) // 获取创建的 testStore() const store = testStore() as any // 赋值 user.id = store.id as string user.username = store.user.username as string user.password = store.user.password as string</script>
实现效果
改变 store 中的值
可以调用 $patch 方法。 它允许您使用部分“state”对象同时应用多个更改:
store.$patch({ user: {id: '2',username: '张三',password: '456789'} })
改变值效果
Actions
Actions 相当于组件中的 methods。 它们可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑:
import { defineStore } from 'pinia'export const testStore = defineStore('testStore', { state: () => ({ // 用户信息user: {username: '',password: ''} }),actions: { // 设置 user setUser(val: any) {this.user = val}}})
<template> <div> <el-input v-model="loginForm.username"></el-input> <el-input v-model="loginForm.password"></el-input> <el-button @click="onLogin()">提交</el-button> <div> <h3>store存储:账号:{{user.username}} ,密码: {{user.password}}</h3> </div> </div></template><script setup lang="ts"> import { testStore } from '@/store/test'; import { ref,reactive } from 'vue'; // from const loginForm = reactive({username: '',password: '' }) // user const user = reactive({username: '',password: '' }) const store = testStore() as any // 点击事件 const onLogin = () => { // store 设置 user store.setUser(loginForm) // 取出设置的user 并且展示 user.username = store.user.username as string user.password = store.user.password as string }</script>
实现效果
六、项目案例(用户登录存储token)
下面是项目中所使用的 Piain 案例,在此解析一下。
main.ts
- 注册 Pinia
- 注册 Pinia 插件(全局对象)
import { createPinia } from 'pinia'import { registerStore } from './store'app.use(createPinia())// 注册 Pinia 插件(全局对象)registerStore()
index.ts(全局对象插件)
作用:将 Store 作为静态属性,全局对象。
import { userStore } from './modules/user'const store: any = {}export const registerStore = () => {store.userStore = userStore()}export default store
使用
store.userStore.accountLoginAction(loginForm) 是可以直接使用的
<script setup lang="ts">// 这里指的是 store 目录下的全局对象index 文件import store from '@/store'// from 表单对象const loginForm = reactive({username: constant.env.PROD " />