vue3.0(4):vuex的基本使用(基于vue3.x)

本文详细介绍了 Vuex 的安装、核心概念,包括响应式状态、提交 mutation、使用 action、getter 和模块。通过示例展示了如何在 Vue 组件中使用 Vuex 管理状态,以及如何组织项目结构。同时,强调了 Vuex 中状态管理的规则和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方文档

传送门

安装

安装vuex

npm install vuex@next --save
yarn add vuex@next --save

安装Promise(Vuex 依赖 Promise)

npm install es6-promise --save # npm
yarn add es6-promise # Yarn

核心概念

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

store.js

import { createStore } from 'vuex'

//创建一个新的store实例
const store = createStore({
    //存储数据
    state() {
        return {
            count: 0
        }
    },
    //修改数据的方法
    mutations: {
        increment(state) {
            state.count++
        }
    }
})

export default store;

main.js

import store from './store/store'

const app = createApp(App)
//将store实例作为插件安装
app.use(store)

你可以通过 store.state 来获取状态对象,并通过 store.commit 方法触发状态变更:

<template>
  <div>
    <el-button type="primary" @click="increment">修改状态</el-button>
    <div>状态值: {{ count }}</div>
  </div>
</template>

<script>
import { useStore } from "vuex";
import { ref } from "vue";
export default {
  setup() {
    //获取store实例
    let store = useStore();
    let count = ref(0);
    let increment = () => {
      //修改状态
      store.commit("increment");
      //获取状态
      count.value = store.state.count;
    };
    return {
      increment,
      count,
    };
  },
};
</script>

<style scoped lang="scss">
</style>

在这里插入图片描述
在这里犯了个错误,就是导入useStoreref 这两个不是来自一个包

State

Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。

  • 获取状态
//方式1:通过ref返回一个响应式数据,就是上面那个例子
//方式2:通过计算属性返回一个响应式数据
console.log(computed(() => store.state.count).value);
//方式3:mapState 辅助函数,这里不介绍

Getter

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数。
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。

实例: 根据用户id获取用户名

  • store.js
import { createStore } from 'vuex'

//创建一个新的store实例
const store = createStore({
    //存储数据
    state() {
        return {
            userList: [
                { id: 1, name: '张三' },
                { id: 2, name: '李四' }
            ]
        }
    },
    getters: {
        //根据用户id获取用户名
        getNameById: (state) => (id) => {
            let user = state.userList.find(e => e.id == id)
            if (user) {
                return user.name
            }
        },

        //返回用户列表
        getUserList: (state) => {
            return state.userList
        }

    }
})

export default store;
  • vuexTest.vue
<template>
  <div>
    <el-button type="primary" @click="getUserInfo">获取用户</el-button>
    <div>id为1的用户是: {{ userName }}</div>
  </div>
</template>

<script>
import { useStore } from "vuex";
import { ref } from "vue";
export default {
  setup() {
    //获取store实例
    let store = useStore();
    let userName = ref("");
    let getUserInfo = () => {
      userName.value = store.getters.getNameById(1);
      console.log("用户列表:", store.getters.getUserList);
    };
    return {
      getUserInfo,
      userName,
    };
  },
};
</script>

<style scoped lang="scss">
</style>
  • mapGetters 辅助函数(略)

Mutation

  • 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})
  • 你不能直接调用一个 mutation 处理函数。你需要以相应的 type 调用 store.commit 方法:
store.commit('increment')
  • 提交载荷(Payload)
//可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload)
//在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)
  • Mutation 必须是同步函数

Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

  • 分发 Action、在组件中分发 Action、组合 Action(略)

Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
  • 模块的局部状态

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。

const moduleA = {
  state: () => ({
    count: 0
  }),
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

同样,对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}
  • 命名空间、模块动态注册(略)

进阶

项目结构

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  • 应用层级的状态应该集中到单个 store 对象中。
  • 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  • 异步逻辑都应该封装到 action 里面。
  • 大型应用,最好把vuex相关代码分割到模块中
├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

其他内容略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无知的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值