体验 Vue 生态两种主流状态管理方案在语法、类型支持和开发体验上的差异
import { createStore } from 'vuex'
export default createStore({
// State
state: {
count: 0,
user: null
},
// Getters
getters: {
doubleCount: state => {
return (state?.count ?? 0) * 2
},
isLoggedIn: state => !!(state?.user)
},
// Mutations (同步)
mutations: {
INCREMENT(state) {
state.count = (state?.count ?? 0) + 1
},
SET_USER(state, user) {
state.user = user
}
},
// Actions (可异步)
actions: {
incrementAsync({ commit }) {
setTimeout(() => {
commit('INCREMENT')
}, 1000)
},
async fetchUser({ commit }, userId) {
const response =
await fetch(\`/api/users/\${userId}\`)
const user = await response.json()
commit('SET_USER', user)
}
}
})
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double: {{ doubleCount }}</p>
<button @click="increment">+</button>
<button @click="incrementAsync">+ (async)</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount'])
},
methods: {
...mapMutations(['INCREMENT']),
...mapActions(['incrementAsync']),
increment() {
this.INCREMENT()
}
}
}
</script>
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
// 方式1: 组合式 API (推荐)
export const useCounterStore = defineStore('counter', () => {
// State
const count = ref(0)
const user = ref(null)
// Getters
const doubleCount = computed(() => (count.value ?? 0) * 2)
const isLoggedIn = computed(() => !!user.value)
// Actions
function increment() {
count.value = (count.value ?? 0) + 1
}
async function incrementAsync() {
await new Promise(r => setTimeout(r, 1000))
increment()
}
async function fetchUser(userId) {
const response = await fetch(\`/api/users/\${userId}\`)
user.value = await response.json()
}
return {
count, user,
doubleCount, isLoggedIn,
increment, incrementAsync, fetchUser
}
})
// 方式2: 选项式 API
export const useCounterStoreOld = defineStore('counter', {
state: () => ({
count: 0,
user: null
}),
getters: {
doubleCount: (state) => (state?.count ?? 0) * 2
},
actions: {
increment() {
this.count = (this?.count ?? 0) + 1
}
}
})
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment()">+</button>
<button @click="counter.incrementAsync()">+ (async)</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
// 直接获取 store 实例
const counter = useCounterStore()
// 或者直接解构(但会失去响应式!)
// const { count, increment } = useCounterStore() // ❌ 错误
// 正确解构方式:使用 storeToRefs
// import { storeToRefs } from 'pinia'
// const { count, doubleCount } = storeToRefs(counter)
// const { increment } = counter
</script>