vuex 和 pinia 的学习使用

vuex的使用

  • 定义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>
相关推荐
沐知全栈开发2 小时前
SQL LEN() 函数详解
开发语言
钟离墨笺2 小时前
Go语言--2go基础-->基本数据类型
开发语言·前端·后端·golang
爱吃泡芙的小白白2 小时前
Vue 3 核心原理与实战:从响应式到企业级应用
前端·javascript·vue.js
小郭团队2 小时前
1_7_五段式SVPWM (传统算法反正切+DPWM3)算法理论与 MATLAB 实现详解
开发语言·嵌入式硬件·算法·matlab·dsp开发
卓怡学长3 小时前
m115乐购游戏商城系统
java·前端·数据库·spring boot·spring·游戏
C+-C资深大佬3 小时前
C++风格的命名转换
开发语言·c++
No0d1es3 小时前
2025年粤港澳青少年信息学创新大赛 C++小学组复赛真题
开发语言·c++
点云SLAM3 小时前
C++内存泄漏检测之手动记录法(Manual Memory Tracking)
开发语言·c++·策略模式·内存泄漏检测·c++实战·new / delete
码上成长3 小时前
JavaScript 数组合并性能优化:扩展运算符 vs concat vs 循环 push
开发语言·javascript·ecmascript