vuex的使用
javascript
复制代码
//复杂项目将 store 拆分为多个模块,每个模块有自己的 state/mutations/actions/getters。
const cartModule = {
namespaced: true, // 开启命名空间(必开,避免命名冲突)
state: { goods: [] },
mutations: {
addGoods(state, good) {
state.goods.push(good)
}
},
actions: {
asyncAddGoods({ commit }, goods) {
commit('addGoods', goods)
}
},
getters: {
doubleCounter(state) {
return state.goods
}
}
}
const store = new Vuex.Store({
state:{ // 根state的数据
goods:[]
},
getters:{ // 根模块的 getters
doubleCounter(state) {
return state.goods
}
},
mutations: { // 根模块的 mutations
addGoods(state, good) {
state.goods.push(good)
}
},
actions: { // 根模块的 actions
asyncAddGoods({ commit }, goods) {
commit('addGoods', goods)
}
},
modules: { // 子模块
cart: cartModule // 模块名:cart
}
})
javascript
复制代码
// 访问命名空间模块的内容
// 1. 直接访问state:模块名.属性
this.$store.state.cart.goods
// 2. 提交命名空间mutation:模块名/mutation名
this.$store.commit('cart/addGoods', { name: '手机' })
// 3. 提交命名空间mutation:根模块的mutation名
this.$store.commit('addGoods', { name: '电脑' })
// 4. 分发命名空间action:模块名/action名
this.$store.dispatch('cart/asyncAddGoods', { name: '电脑' })
// 5. 分发命名空间action:根模块的action名
this.$store.dispatch('asyncAddGoods', { name: '电脑' })
// 6. 访问命名空间getter:模块名/getter名
this.$store.getters['cart/goodsCount']
// 7. 辅助函数映射(指定命名空间)
...mapMutations('cart', ['addGoods']), // 第一个参数是模块名
...mapActions('cart', ['asyncAddGoods'])
...mapState('cart', ['goods'])// 映射 cart 模块的 state
...mapState(['goods']) //映射根state的数据
...mapGetters('cart',['doubleCounter']) // 映射 cart 模块的 getters
...mapGetters(['doubleCounter']) // 映射根getters的数据
pinia的使用
javascript
复制代码
// src/store/counter.js
import { defineStore } from 'pinia'
/**
* 定义 Store:
* 1. 第一个参数是唯一 ID(必须),作为 Store 的命名空间,不可重复
* 2. 第二个参数是配置对象,包含 state/getters/actions
* 命名规范:use + 模块名 + Store(如 useCounterStore)
*/
export const useCounterStore = defineStore('counter', {
// 1. 状态:存储数据(类似 Vuex 的 state,必须是函数返回对象,避免共享引用)
state: () => ({
count: 0, // 基础数值
userInfo: { // 嵌套对象
name: '张三',
age: 20
},
goodsList: [] // 数组
}),
// 2. 计算属性:派生状态(类似 Vuex 的 getters,缓存结果)
getters: {
// 基础用法:接收 state 作为参数
doubleCount: (state) => state.count * 2,
// 访问当前 Store 的其他 getter:用 this(需注意 TS 类型,JS 可直接用)
tripleCount() {
return this.count * 3
},
// 带参数的 getter(返回函数,灵活传参)
getUserAgeDesc: (state) => (isAdult) => {
return isAdult
? `${state.userInfo.name} 是成年人(${state.userInfo.age}岁)`
: `${state.userInfo.name} 是未成年人(${state.userInfo.age}岁)`
}
},
// 3. 动作:处理逻辑(类似 Vuex 的 actions,支持同步/异步,无 mutations)
actions: {
// 同步修改状态
increment(num = 1) {
this.count += num // 直接修改 state,无需 commit
},
// 异步修改状态(模拟接口请求)
async asyncIncrement(num) {
try {
// 模拟异步操作(如接口请求)
await new Promise(resolve => setTimeout(resolve, 1000))
this.count += num // 异步完成后直接修改 state
} catch (err) {
console.error('异步加值失败:', err)
}
},
// 复杂逻辑:修改多个状态
updateUserInfo(newInfo) {
this.userInfo = { ...this.userInfo, ...newInfo } // 合并新信息
this.count += 1 // 同时修改 count
},
// 批量添加商品
addGoodsBatch(goods) {
this.goodsList.push(...goods)
}
}
})
javascript
复制代码
<!-- src/components/Counter.vue -->
<template>
<div class="counter">
<!-- 直接访问 state -->
<p>基础计数:{{ counterStore.count }}</p>
<!-- 访问 getter -->
<p>双倍计数:{{ counterStore.doubleCount }}</p>
<p>三倍计数:{{ counterStore.tripleCount }}</p>
<p>{{ counterStore.getUserAgeDesc(true) }}</p>
<!-- 按钮触发 action -->
<button @click="handleAdd">同步加1</button>
<button @click="handleAsyncAdd">异步加2</button>
<button @click="handleUpdateUser">更新用户信息</button>
<button @click="handleAddGoods">批量添加商品</button>
<button @click="handleReset">重置状态</button>
</div>
</template>
<script setup>
// 1. 导入定义好的 Store
import { useCounterStore } from '@/store/counter'
// 2. 创建 Store 实例(组件内唯一,重复调用也返回同一个实例)
const counterStore = useCounterStore()
// 3. 定义事件处理函数(调用 Store 的 actions/直接修改 state)
// 同步加1
const handleAdd = () => {
counterStore.increment(1)
}
// 异步加2
const handleAsyncAdd = () => {
counterStore.asyncIncrement(2)
}
// 更新用户信息
const handleUpdateUser = () => {
counterStore.updateUserInfo({ age: 25, name: '李四' })
}
// 批量添加商品
const handleAddGoods = () => {
counterStore.addGoodsBatch([{ name: '苹果', price: 10 }, { name: '香蕉', price: 5 }])
}
// 重置所有状态到初始值
const handleReset = () => {
counterStore.$reset()
}
</script>