Pinia
# Pinia
对于状态管理
在vue中可以通过 export const state = reactive({})
来共享一个全局状态,当然这对单页应用来说是可以的,但是如果是在服务端渲染,会出现一些二安全问题。Pinia能解决这个问题
# 安装
yarn add pinia
# 或者使用 npm
npm install pinia
# 基础使用
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
// 属性
state: () => {
return { count: 0 }
},
// 也可以这样定义
// state: () => ({ count: 0 })
// 方法
actions: {
increment() {
this.count++
},
},
})
在一个组件中使用
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.count++
// 自动补全! ✨
counter.$patch({ count: counter.count + 1 })
// 或使用 action 代替
counter.increment()
</script>
<template>
<!-- 直接从 store 中访问 state -->
<div>Current Count: {{ counter.count }}</div>
</template>
# 高级用法(常用的)
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('coubter',()=>{
const count = ref(0)
function increment(){
count.value++
}
return { count , increment}
})
# 我在日常的工作项目中的一些写法:
用于的是数据一开始get的时候的状态管理,管理的展示部分的也就是get的数据
import { ICommunityGroup, communityGroupApi } from '@/api/modules/setting'
import { defineStore, storeToRefs } from 'pinia'
import { ref } from 'vue'
export const communityGroupStore = defineStore('communityGroupStore', () => {
const communityGroupData = ref<ICommunityGroup[]>()
const communityGroupPatams = ref({
index: 1,
title: '',
group_ids: [] as string[],
})
const refetchCommunityGroup = ref(async () => {
try {
const { data } = await communityGroupApi.getComGroup(communityGroupPatams.value)
if (data) {
communityGroupData.value = data
}
} catch (error) {}
})
return { communityGroupData, refetchCommunityGroup }
})
export const useCommunityGroupStore = () => storeToRefs(communityGroupStore())
组件使用
<script>
import { useCommunityGroupStore } from '@/store/modules/setting'
const { communityGroupData, refetchCommunityGroup } = useCommunityGroupStore()
onMounted(async () => {
// 注意返回的ref类型的所以要加.value
communityGroupPatams.value = {
index: 1,
title: '123',
group_ids: [] as string[],
}// 修改参数
await refetchCommunityGroup.value() // 根据参数调用get接口
console.log(communityGroupData.value) // 打印值,一般这个值就是展示的数据了
})
</script>
# Vuex
Vuex 是什么? | Vuex (opens new window)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库
# npm 或Yarn安装
npm install vuex@next --save
yarn add vuex@next --save
# 配置
新建store文件->index.js,进行如下配置,在main.js中进行引入
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//数据,相当于data
state: {
},
getters: {
},
//里面定义方法,操作state方发
mutations: {
},
// 操作异步操作mutation
actions: {
},
modules: {
},
})
mian.js中
import vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h = > h(App)
}).$mount('#app')
vuex中一共有五个状态 State Getter Mutation Action Module
在Vuex中,我们需要先定义store,然后在组件中通过mapState、mapGetters、mapActions、mapMutations等方式来访问store。
// store.js
import Vuex from 'vuex'
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
},
},
actions: {
increment({ commit }) {
commit('increment')
},
decrement({ commit }) {
commit('decrement')
},
},
})
// 组件中使用
import { mapState, mapActions } from 'vuex'
export default {
computed: mapState({
count: state => state.count,
}),
methods: mapActions(['increment', 'decrement']),
}
# Pinia和vuex在使用上有什么区别
# 架构与使用的关键差异
# 状态定义与修改
Vuex要求通过严格的mutation来修改状态,这意味着每一个状态变更都需要经过预定义的mutation函数:
// Vuex典型状态管理
const store = new Vuex.Store({
state: {
count: 0,
userInfo: null
},
mutations: {
INCREMENT(state) {
state.count++
},
SET_USER_INFO(state, userInfo) {
state.userInfo = userInfo
}
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('INCREMENT')
}, 1000)
}
}
})
相比之下,Pinia允许直接修改状态,代码更加简洁自然:
// Pinia的状态管理
const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
userInfo: null
}),
actions: {
increment() {
this.count++ // 直接修改,无需commit
},
async fetchUserInfo() {
// 支持异步操作
const response = await fetchUser()
this.userInfo = response.data
}
}
})
# 响应式与类型支持
Pinia原生支持TypeScript,提供更好的类型推导。状态默认是响应式的,组件可以直接使用store中的状态,无需额外的响应式转换。
# 模块化与代码组织
Vuex通过modules实现模块化,需要手动处理命名空间:
const moduleA = {
namespaced: true,
state: { ... },
mutations: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA
}
})
Pinia的模块化更加直观,可以轻松地创建和组合多个store:
const useUserStore = defineStore('user', { ... })
const useProductStore = defineStore('product', { ... })
# 性能与生态
- Pinia更轻量(约1.6kb)
- 运行时开销更低
- 支持Tree-Shaking
Pinia的出现不仅仅是一个技术迭代,更体现了Vue生态对开发体验的持续追求 —— 让状态管理变得更加直观、高效和易用。它代表了前端状态管理的一个重要发展方向。