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>
相关推荐
牛奔19 分钟前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路4 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
lly2024066 小时前
Bootstrap 警告框
开发语言
2601_949146536 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧6 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
KYGALYX7 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
zmzb01037 小时前
C++课后习题训练记录Day98
开发语言·c++