最近学习cloud项目,前端使用到 vue3 + ts 等技术,其中包括 pinia ,从一脸懵到渐渐清晰过程,在此记录一下,若有不足,希望大佬可以指出。
中文官方文档:https://pinia.web3doc.top/
Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。实际上,pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名pinia,而没有取名Vuex,所以大家可以直接将pinia比作为Vue3的Vuex。
Vuex 的优点:
Vuex 的缺点:
pinia 的优点:
CMD命令:
npm install pinia
main.ts:
import { createPinia } from 'pinia'
app.use(createPinia())
import { defineStore } from 'pinia'
export const userStore = defineStore('userStore', {
state: () => ({
// 内容
}),
actions: {
// 内容
}
})
在深入了解核心概念之前,我们需要知道 Store 是使用 defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递:
import { defineStore } from 'pinia'
// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id (userStore)
export const useStore = defineStore('userStore', {
// other options...
})
大多数时候,state 是 store 的核心部分。 我们通常从定义应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数(类似 data)。 Pinia 在服务器端和客户端都可以工作。
import { defineStore } from 'pinia'
// 唯一 ID: testStore
export 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>
可以调用 $patch 方法。 它允许您使用部分“state”对象同时应用多个更改:
store.$patch({
user: {
id: '2',
username: '张三',
password: '456789'
}
})
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>
下面是项目中所使用的 Piain 案例,在此解析一下。
import { createPinia } from 'pinia'
import { registerStore } from './store'
app.use(createPinia())
// 注册 Pinia 插件(全局对象)
registerStore()
作用:将 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 ? '' : 'admin',
password: constant.env.PROD ? '' : 'admin',
key: '',
captcha: ''
})
// 点击事件
const onLogin = () => {
// 这是校验表单,可以忽略
loginFormRef.value.validate((valid: boolean) => {
if (!valid) {
return false
}
// 用户登录
store.userStore
// userStore 中的 accountLoginAction
.accountLoginAction(loginForm)
.then(() => {
router.push({ path: '/home' })
})
.catch(() => {
onCaptcha()
})
})
}
</script>
import { defineStore } from 'pinia'
// 登录的 api 接口文件
import { useAccountLoginApi, useMobileLoginApi, useLogoutApi } from '@/api/auth'
// api 接口文件
import { useUserInfoApi } from '@/api/sys/user'
// 缓存文件
import cache from '@/utils/cache'
export const userStore = defineStore('userStore', {
state: () => ({
// 用户信息
user: {
id: '',
username: '',
avatar: ''
}
}),
actions: {
// 设置token
setToken(val: any) {
this.token = val
// 使用到 cache 文件
cache.setToken(val)
},
// 异步账号登录
async accountLoginAction(loginForm: any) {
// 登录请求,获取返回 data
const { data } = await useAccountLoginApi(loginForm)
// 设置token
this.setToken(data.access_token)
}
}
})
从上面缓存 token cache.setToken(val)
import { SessionStorage, Storage } from '@/utils/storage'
// 设置缓存的key文件
import CacheKey from '@/utils/cache/key'
// 缓存
class Cache {
// 获取 token
getToken = (): string => {
return Storage.getItem(CacheKey.TokenKey) || ''
}
// 设置 token
setToken = (value: string) => {
Storage.setItem(CacheKey.TokenKey, value)
}
}
export default new Cache()
/**
* window.localStorage 浏览器永久缓存
* @method setItem 设置缓存
* @method getItem 获取缓存
* @method removeItem 移除缓存
* @method clear 移除全部缓存
*/
export const Storage = {
setItem(key: string, value: any) {
if (value === undefined) {
return
}
window.localStorage.setItem(key, JSON.stringify(value))
},
getItem(key: string) {
let json: any = window.localStorage.getItem(key)
return JSON.parse(json)
},
removeItem(key: string) {
window.localStorage.removeItem(key)
},
clear() {
window.localStorage.clear()
}
}
/**
* window.sessionStorage 浏览器临时缓存
* @method setItem 设置缓存
* @method getItem 获取缓存
* @method removeItem 移除缓存
* @method clear 移除全部缓存
*/
export const SessionStorage = {
setItem(key: string, value: any) {
if (value === undefined) {
return
}
window.sessionStorage.setItem(key, JSON.stringify(value))
},
getItem(key: string) {
let json: any = window.sessionStorage.getItem(key)
return JSON.parse(json)
},
removeItem(key: string) {
window.sessionStorage.removeItem(key)
},
clear() {
window.sessionStorage.clear()
}
}