Pinia
Pinia
是 Vue
的存储库,它允许您跨组件/页面共享状态。
Pinia
优点
Pinia
提供了一个更简单的 API
,具有更少的规范,提供了 Composition-API
风格的 API
,最重要的是,在与 TypeScript
一起使用时具有可靠的类型推断支持。
Pinia
文档
Pinia
基本使用
1、初始化项目
推荐使用pnpm
,可以参考pnpm文档。
# pnpm
pnpm create vite vite2-vue3 -- --template vue
2、安装Pinia
pnpm i pinia
3、挂载Pinia
在main.js
中import { createPinia } from 'pinia'
,然后createApp(App).use(createPinia())
。完整代码:
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
import router from '@/router'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import '@/styles/index.scss' // global css
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(createPinia())
app.use(router)
app.mount('#app')
4、定义Store
使用 defineStore()
定义。
import { loginAction } from '@/api/user'
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => {
return {
username: '',
avatar: ''
}
},
actions: {
update_username(username) {
this.$patch((state) => {
state.username = username
})
},
login(data) {
return new Promise((resolve, reject) => {
loginAction(data).then(res => {
if (res.code === 200) {
resolve(null)
} else {
reject(res)
}
}).catch((error) => {
reject(error)
})
})
}
}
})
5、使用Store
一旦 store 被实例化,你就可以直接在 store 上访问 state
、getters
和 actions
中定义的任何属性。store
是一个用 reactive
包裹的对象。
解构方法
1、普通解构(破坏了响应式)
const userStore = useUserStore()
// ❌ 这不起作用,因为它会破坏响应式
// 这和从 props 解构是一样的
const { name } = userStore
console.log(name) // 一直会是 "admin"
// 这将是响应式的
const name2 = computed(() => userStore.name)
2、storeToRefs()
为了从 Store
中提取属性同时保持其响应式,需要使用storeToRefs()
。 它将为任何响应式属性创建 refs。
const userStore = useUserStore()
// `name` 和 `avatar` 是响应式引用
// 这也会为插件添加的属性创建引用
// 但跳过任何 action 或 非响应式(不是 ref/reactive)的属性
const { name, avatar } = storeToRefs(userStore)
使用 store
中的 actions
const userStore = useUserStore()
let data = {}
// 模拟数据
data.mobile = ''
data.password = ''
data.type = 'mobile'
userStore
.login(data)
.then(() => {
ElMessage({ message: '登录成功', type: 'success' })
})
.catch((res) => {
ElMessage({ message: res.message, type: 'error' })
})
6、改变state
可以通过下列方式改变state
:
- 简单数据直接通过在方法中操作 store.属性名 来修改
- 通过 $patch + 对象
- $patch 方法也接受一个函数来批量修改集合内部分对象
// 1、简单数据直接通过在方法中操作 store.属性名 来修改
userStore.username = 'admin'
// 2、通过 $patch + 对象
userStore.$patch({
username: 'admin',
avatar: 'https://s.elink.chinabond.com.cn/storage/uploads/resource/165672667862bfa49676ed4.jpeg',
})
// 3、$patch 方法也接受一个函数来批量修改集合内部分对象
update_username(username) {
this.$patch((state) => {
state.username = username
})
}