前言
作为前端开发,你肯定知道状态管理是日常开发很重要的一部分。你肯定也听过许多状态管理工具,今天我们说一下 Vue 系列的新起之秀 Pinia。
什么是 Pinia
Pinia 和 Vuex 一样是专门为 Vue 设计的状态管理库,它允许你跨组件或页面共享状态,Api 设计比 Vuex 更简单易学,且同时支持 Vue2.0 和 Vue3.0。
安装
代码语言:javascript复制yarn add pinia
// 或者使用 npm
npm install pinia
创建一个 Pinia 实例 (根 Store ) 并将其传递给应用:
代码语言:javascript复制import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
如何创建 Store
在创建 Store 之前我们先简单描述一下什么是 Store
Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它承载着全局状态,每个组件都可以读取和写入它。它有三个概念:State、Getter 和 Action,可以想象成组件中的 Data
、 Computed
和 Methods
。
创建一个 Store,在 src/stores 创建一个 counter.ts
代码语言:javascript复制// stores/counter.ts
// options 模式
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
actions: {
increment() {
this.count
},
},
})
// Setup 模式
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value
}
return { count, increment }
})
上述代码就是创建一个 Store,DefineStore 可以随意命名,但最好保持 Use 这种风格,DefineStore 第一个参数是唯一的,不可重复,因为是应用中 Store 的唯一 ID,Pinia 将用 ID 连接 Store 和 Devtools。DefineStore 的第二个参数可以接受 Setup 函数或 Option 对象。
State
State 的使用
代码语言:javascript复制import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<div class="greetings">
{{counter.count}}
</div>
</template>
修改 State
代码语言:javascript复制// 直接修改
counter.count
// 或者使用 $patch 修改 (可以修改多个属性)
counter.$patch({
count: counter.count 1,
})
重置 State
代码语言:javascript复制// 通过调用 store 的 $reset() 方法将 state 重置为初始值。
counter.$reset()
解构:
代码语言:javascript复制import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
const {count} = counter
</script>
<template>
<div class="greetings">
{{counter.count}}
{{count}}
</div>
</template>
State 也可以使用解构,但是解构会失去响应式,需要 StoreToRefs 避免丢失响应式
代码语言:javascript复制import { storeToRefs } from 'pinia'
const counter = useCounterStore()
const {count} = storeToRefs(counter)
Getter
Getter 完全等同于 Store 的 State 的计算属性。写法也类似,可以使用 this 访问整个 Store 的实例,甚至可以访问其他 Store 的 Getter,而且可以和 Vue 一样返回一个函数 接受参数(但是这样 Getter 将不再被缓存,只是个被调用的函数),使用同 State 访问模式一样。
代码语言:javascript复制import { useOtherStore } from './other-store'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
getters: {
// 使用 state 可以自动推到出类型
doubleCount(state) {
return state.count * 2
},
// 返回类型必须明确设置
doublePlusOne(): number {
return this.doubleCount 1
},
//还可以访问其他 getter
otherGetter(state) {
const otherStore = useOtherStore()
return state.count otherStore.count
},
},
actions: {
increment() {
this.count
},
},
})
Action
Action 相当于组件中的 Methods,类似 Getter,Action 也可通过 this 访问整个 Store 的实例 Action 也可以是异步的,还可以访问其他Store 的 Action。
代码语言:javascript复制import { useAuthStore } from './user'
export const useCounterStore = defineStore('counter', {
state: () => {
return {
userInfo: {}
}
},
actions: {
async fetchUserInfo() {
const auth = useAuthStore()
if (auth.isAuthenticated) {
this.userInfo = await fetchUserInfo()
}
},
},
})
调用
代码语言:javascript复制<script setup>
const store = useCounterStore()
// 将 action 作为 store 的方法进行调用
store.fetchUserInfo()
</script>
<template>
<!-- 即使在模板中也可以 -->
<button @click="store.fetchUserInfo()">点击我</button>
</template>
总结
以上就是 Pinia 的基本使用。回顾以前使用的 Vuex 是不是 Api 是不是非常简洁,Pinia 抛弃了 Mutation 和 Module,只保留State、Getter 和 Action,而且使用方法和组件中 Data
、 Computed
和 Methods
类似,上手零成本。而且支持 ts,极致轻量化代码只有1kb左右。
参考链接
https://pinia.web3doc.top/