Vue2之Vuex

文章目录

  • 数据准备
    • 新建项目
    • 选择模块安装
    • vscode工具打开 删除无用文件
      • 删除src/assets文件下的所有内容
      • 删除src/components文件下的所有内容
      • 修改src/app.vue
      • vscode运行项目
  • 一、 概述
    • 1.是什么
    • 2. 使用场景
    • 3.优势
    • 4 Vuex流程图
    • 5.注意:
  • 二、需求: 多组件共享数据
    • 创建三个组件, 目录如下
    • 源代码如下
      • Son1.vue
      • Son2.vue
      • App.vue
      • main.js不变
    • 说明
  • 三、vuex 的使用 - 创建仓库
    • 1.安装 vuex
    • 2.新建 store/index.js 专门存放 vuex
    • 3.创建仓库 store/index.js
    • 4 在 main.js 中导入挂载到 Vue 实例上
    • 5.测试打印Vuex
  • 四、核心概念 - state 状态
    • 4.1 概念
    • 4.2 store中定义state属性提供数据
    • 4.3 访问Vuex中的数据
    • 4.4 组件通过$store访问Vuex中的数据
      • 4.4.1 模板中使用
      • 4.4.2. 组件逻辑中使用
      • 4.4.3 js文件中使用
      • 4.4.4 修改src/components/Son1.vue
    • 4.5 组件通过mapState获取 state中的数据
      • 4.5.1 mapState作用
      • 4.5.2 修改src/components/Son2.vue
      • 4.5.3 运行结果
  • 五、开启严格模式及Vuex的单项数据流
    • 1.目标
    • 2.直接在组件中修改Vuex中state的值
      • Son1.vue
      • 运行结果
    • 3.开启严格模式
      • 严格模式有什么用
      • 运行结果
  • 六、mutations+mapMutations同步修改仓库属性的值
    • 6.1 概念
    • 6.2 store中定义mutations
      • 6.2.1 语法
      • 6.2.2 代码:修改src/store/index.js
    • 6.3 组件中使用$store.emit()调用mutations方法
      • 6.3.1 修改src/components/Son1.vue
      • 6.3.2 运行结果
    • 6.4 组件中使用mapMutations辅助函数调用mutations
      • 6.4.1 mapMutations用法
      • 6.4.2 代码实现
      • 6.4.3 运行结果
  • 七、actions+mapActions异步修改仓库属性的值
    • 7.1 概念
    • 7.2 store中定义actions
      • 7.2.1 语法
      • 7.2.2 代码:修改src/store/index.js
    • 7.3 组件中使用$store.dispatch()调用actions的方法
      • 7.3.1 语法
      • 7.3.2 修改src/components/Son1.vue
      • 7.3.3 运行结果
    • 7.4 组件中使用mapActions调用actions的方法
      • 7.4.1 mapActions语法
      • 7.4.2 代码实现
      • 7.4.3 运行结果
  • 八、核心概念-getters
    • 8.1 概念getters
    • 8.2 store中定义getters
      • 8.2.1 语法
      • 8.2.2 代码:修改src/store/index.js
    • 8.3 组件中使用$store.commit调用getters的方法
      • 8.3.1 语法
      • 8.3.2 修改src/components/Son1.vue
      • 8.3.3 运行结果
    • 8.4 组件中使用mapGetters调用getters的方法
      • 8.4.1 mapGetters语法
      • 8.4.2 代码实现
      • 8.4.3 运行结果
  • 9 前面四个属性的总结
  • 十、核心概念 - 模块 module
    • 10.1 概念
    • 10.2 模块定义
      • 10.2.1 新建src/store/modules/user.js
      • 10.2.2 新建src/store/modules/setting.js
      • 10.2.3 修改src/store/index.js
      • 10.2.4 修改src/components/Son1.vue
      • 10.2.5 修改src/components/Son2.vue
      • 10.2.6 运行结果如下
    • 10.3 命名空间
      • 10.3.1 什么是命名空间
      • 10.3.2 如何在子模块中开启命名空间
    • 10.4 分模块的state使用和获取
    • 10.5 分模块的mutations使用和获取
    • 10.6 分模块的actions使用和获取
    • 10.7 分模块的getters使用和获取
    • 10.8 代码演示
      • 修改src/components/Son1.vue
      • 修改src/components/Son2.vue
  • 总结
    • 流程图
    • 不使用分模块的写法
    • 使用分模块写法
    • 开启严格模式
    • 开启命名空间

数据准备

新建项目

  1. 检查版本
    node版本:20.18.0
    @vue/cli版本:5.0.8
  2. 新建文件夹,输入cmd回车打开命令行窗口
    在这里插入图片描述
  3. 命令行窗口:输入指令vue create 项目名
    在这里插入图片描述

选择模块安装

在这里插入图片描述

vscode工具打开 删除无用文件

删除src/assets文件下的所有内容

删除src/components文件下的所有内容

修改src/app.vue

<template><div id="app"></div>
</template><script>export default {name: 'App'
}
</script><style lang="scss">
</style>

vscode运行项目

快捷键打开终端Ctrl + Shift + 反引号 打开终端。反引号是tab键上面那个
运行如下指令启动项目

npm run serve

一、 概述

1.是什么

Vuex 是一个 Vue 的 状态管理工具,状态就是数据。
官网如下:https://vuex.vuejs.org/zh/

大白话:Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如:购物车数据 个人信息数

2. 使用场景

  • 某个状态 在 很多个组件 来使用 (个人信息)
    主页需要展示 XXX订单需要写你的名字等等。
  • 多个组件 共同维护 一份数据 (购物车)
    在这里插入图片描述

3.优势

  • 共同维护一份数据,数据集中化管理
  • 响应式变化
  • 操作简洁 (vuex提供了一些辅助函数)
    在这里插入图片描述

4 Vuex流程图

这个图等讲完后就能看懂了。
在这里插入图片描述

5.注意:

官方原文:

  • 不是所有的场景都适用于vuex,只有在必要的时候才使用vuex
  • 使用了vuex之后,会附加更多的框架中的概念进来,增加了项目的复杂度 (数据的操作更便捷,数据的流动更清晰)

Vuex就像《近视眼镜》, 你自然会知道什么时候需要用它~

二、需求: 多组件共享数据

目标:基于脚手架创建项目,构建 vuex 多组件数据共享环境
在这里插入图片描述
效果是三个组件共享一份数据:

  • 任意一个组件都可以修改数据
  • 三个组件的数据是同步的

创建三个组件, 目录如下

|-components
|--Son1.vue
|--Son2.vue
|-App.vue

源代码如下

Son1.vue

<template><div class="box"><h2>Son1 子组件</h2>从vuex中获取的值: <label></label><br><button>值 + 1</button></div>
</template><script>
export default {name: 'Son1Com'
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

Son2.vue

<template><div class="box"><h2>Son2 子组件</h2>从vuex中获取的值:<label></label><br /><button>值 - 1</button></div>
</template><script>
export default {name: 'Son2Com'
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

App.vue

App.vue在入口组件中引入 Son1 和 Son2 这两个子组件

<template><div id="app"><h1>根组件</h1><input type="text"><Son1></Son1><hr><Son2></Son2></div>
</template><script>
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'export default {name: 'app',data: function () {return {}},components: {Son1,Son2}
}
</script><style>
#app {width: 600px;margin: 20px auto;border: 3px solid #ccc;border-radius: 3px;padding: 10px;
}
</style>

main.js不变

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falsenew Vue({render: h => h(App)
}).$mount('#app')

说明

在这里插入图片描述

上图中的Son1使用原始方法获取值Vuex的值 进行演示讲解
Son2使用辅助函数的方式获取值Vuex的值 进行演示讲解

三、vuex 的使用 - 创建仓库

在这里插入图片描述

1.安装 vuex

安装vuex与vue-router类似,vuex是一个独立存在的插件,如果脚手架初始化没有选 vuex,就需要额外安装。

yarn add vuex@3 或者 npm i vuex@3

注意

  • vue2 安装Vuex3.0 版本 Router 3.0 版本
  • vue3 安装Vuex4.0 版本 Router 4.0 版本

2.新建 store/index.js 专门存放 vuex

为了维护项目目录的整洁,在src目录下新建一个store目录其下放置一个index.js文件。 (和 router/index.js 类似)

在这里插入图片描述

3.创建仓库 store/index.js

// 导入 vue
import Vue from 'vue'
// 导入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)// 创建仓库 store
const store = new Vuex.Store()// 导出仓库
export default store

4 在 main.js 中导入挂载到 Vue 实例上

import Vue from 'vue'
import App from './App.vue'
import store from './store'Vue.config.productionTip = falsenew Vue({render: h => h(App),store
}).$mount('#app')

此刻起, 就成功创建了一个 空仓库!!

5.测试打印Vuex

App.vue

created(){console.log(this.$store)
}

在这里插入图片描述

四、核心概念 - state 状态

4.1 概念

在这里插入图片描述

State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储。即上图的State—>Vue Components

4.2 store中定义state属性提供数据

打开项目中的store.js文件,在state对象中可以添加我们要共享的数据。
修改src/store/index.js

// 导入 vue
import Vue from 'vue'
// 导入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)// 创建仓库 store
const store = new Vuex.Store({// state 状态, 即数据, 类似于vue组件中的data,// 区别:// 1.data 是组件自己的数据, // 2.state 中的数据整个vue项目的组件都能访问到state: {count: 101}
})
// 导出仓库
export default store

4.3 访问Vuex中的数据

问题: 如何在组件中获取count?

  1. 通过$store直接访问 —> {{ $store.state.count }}
  2. 通过辅助函数mapState 映射计算属性 —> {{ count }}(后面讲)

4.4 组件通过$store访问Vuex中的数据

获取 store:1.Vue模板中获取 this.$store2.js文件中获取 import 导入 store模板中:     {{ $store.state.xxx }}
组件逻辑中:  this.$store.state.xxx
JS模块中:   store.state.xxx

4.4.1 模板中使用

组件中可以使用 $store 获取到vuex中的store对象实例,可通过state属性属性获取count, 如下

<h1>state的数据 - {{ $store.state.count }}</h1>

4.4.2. 组件逻辑中使用

将state属性定义在计算属性中 https://vuex.vuejs.org/zh/guide/state.html

<h1>state的数据 - {{ count }}</h1>
// 把state中数据,定义在组件内的计算属性中computed: {count () {return this.$store.state.count}}

4.4.3 js文件中使用

//main.js
import store from "@/store"
console.log(store.state.count)

每次都像这样一个个的提供计算属性, 太麻烦了,我们有没有简单的语法帮我们获取state中的值呢?

4.4.4 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子组件 使用原始方式获取</h2><!-- 模板中使用 --><h4>从vuex中获取count的值:{{$store.state.count}}</h4><!-- 组件逻辑中使用 --><h4>从vuex中获取title的值:{{title}}</h4><br><button @click="handleAdd">值 + 1</button></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

4.5 组件通过mapState获取 state中的数据

4.5.1 mapState作用

mapState是辅助函数,帮助我们把store中的数据 自动 映射到 组件的计算属性中, 它属于一种方便的用法

在这里插入图片描述

4.5.2 修改src/components/Son2.vue

<template><div class="box"><h2>Son2 子组件 使用辅助函数方式获取</h2><h4>从vuex中获取count的值:{{count}}</h4><h4>从vuex中获取title的值:{{title}}</h4><br /><button>值 - 1</button></div>
</template><script>
// 引入 mapState 辅助函数
import { mapState } from "vuex";
export default {name: 'Son2Com',computed: {...mapState(["count", "title"]),// 等价于// count () {//   return this.$store.state.count;// }// title () {//   return this.$store.state.title;// }},
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

4.5.3 运行结果

在这里插入图片描述

五、开启严格模式及Vuex的单项数据流

1.目标

明确 vuex 同样遵循单向数据流,组件中不能直接修改仓库的数据

2.直接在组件中修改Vuex中state的值

在这里插入图片描述

Son1.vue

<template><div class="box"><h2>Son1 子组件</h2>从vuex中获取的值: <label></label><br><!-- 1.绑定点击事件 --><button @click="handleAdd">+ 1</button></div>
</template><script>
export default {name: 'Son1Com',// 定义方法methods: {handleAdd() {this.$store.state.count++}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

运行结果

不会报错,这是因为没有开启严格模式
在这里插入图片描述

3.开启严格模式

严格模式有什么用

通过 strict: true 可以开启严格模式,开启严格模式后,直接修改state中的值会报错

state数据的修改只能通过mutations,并且mutations必须是同步的

在这里插入图片描述

运行结果

在这里插入图片描述

六、mutations+mapMutations同步修改仓库属性的值

6.1 概念

上面说了state中的属性值 不能直接修改就需要使用store的mutations属性定义方法去修改state中的值。
在这里插入图片描述

6.2 store中定义mutations

6.2.1 语法

注意事项

  1. mutations 修改state中的数据, 类似于vue组件中的methods
  2. mutations中属性的方法
    + 第一个参数是当前store的state属性
    + 第二个参数是payload(传递)载荷 用于传递参数
    + 注意:payload(传递)载荷只能有一个,想要传递多个参数要使用对象或者数组的形式。
  3. mutations中的方法, 必须是同步方法。同步方法是指js中的普通方法。异步方法下面会讲。

6.2.2 代码:修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,title: 'hello world'},// mutations 修改state中的数据, 类似于vue组件中的methodsmutations: {// mutations中的方法, //    第一个参数是当前store的state属性//    第二个参数是payload(传递)载荷  用于传递参数//      注意:payload(传递)载荷只能有一个,想要传递多个参数要使用对象或者数组的形式// mutations中的方法, 必须是同步方法// 传单个参数addCount(state, num) {state.count += num},// 传对象subCount(state, obj) {state.count -= obj.numconsole.log(obj.name);}},})export default store

6.3 组件中使用$store.emit()调用mutations方法

6.3.1 修改src/components/Son1.vue

由于上面在main.js全局已经全局挂在了所以不需要导入。

<template><div class="box"><h2>Son1 子组件 使用原始方式获取</h2><!-- 模板中使用 --><h4>从vuex中获取count的值:{{$store.state.count}}</h4><!-- 组件逻辑中使用 --><h4>从vuex中获取title的值:{{title}}</h4><br><button @click="handleAdd">+ 1</button><button @click="$store.commit('addCount', 2)">+ 2</button><button @click="handleSub">- 1</button></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {this.$store.commit('addCount', 1)},handleSub() {this.$store.commit('subCount', {num: 1, name: '张三'})}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

6.3.2 运行结果

在这里插入图片描述

6.4 组件中使用mapMutations辅助函数调用mutations

6.4.1 mapMutations用法

<template><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button>
</template>
<script>
import { mapMutations} from "vuex";
export default {// ...methods: {...mapMutations(["addCount","subCount"])},
}
</script>

6.4.2 代码实现

<template><div class="box"><h2>Son2 子组件 使用辅助函数方式获取</h2><h4>从vuex中获取count的值:{{count}}</h4><h4>从vuex中获取title的值:{{title}}</h4><br /><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button></div>
</template><script>
// 引入 mapState 辅助函数
import { mapState,mapMutations} from "vuex";
export default {name: 'Son2Com',methods: {...mapMutations(["addCount","subCount"])},computed: {...mapState(["count", "title"]),// 等价于// count () {//   return this.$store.state.count;// }// title () {//   return this.$store.state.title;// }},
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

6.4.3 运行结果

在这里插入图片描述

七、actions+mapActions异步修改仓库属性的值

7.1 概念

上面说了使用store的mutations属性定义方法去修改state中的值mutations中的方法,。这个必须是同步方法。

什么是同步方法?:普通方法。
什么是异步方法?:异步方法是指那些不会阻塞主线程执行、允许程序在等待操作完成期间继续执行其他任务的函数。
异步方法有哪些

  1. 回调函数(Callbacks):​将函数作为参数传递给另一个函数,在异步操作完成后被调用。这是最基础的异步模式,但嵌套过多易导致“回调地狱”
    setTimeout(() => {console.log("异步操作完成");
    }, 1000);
    
  2. Promise:ES6引入的异步处理对象,表示一个异步操作的最终状态(pending/fulfilled/rejected)。通过链式调用(.then()/.catch())管理依赖关系,解决回调嵌套问题 。
    const promise = new Promise((resolve, reject) => {setTimeout(() => resolve("成功"), 1000);
    });
    promise.then(result => console.log(result));
    
  3. ​Async/Await​:ES8基于Promise的语法糖。async标记的函数返回Promise,await暂停函数执行直至Promise完成,使异步代码写法类似同步
    async function fetchData() {try {const data = await fetch("/api/data");return data.json();} catch (error) {console.error(error);}
    }
    

作用:mapActions 是把位于 actions中的方法提取了出来,映射到组件methods中。

mutations是同步更新数据 (便于监测数据的变化, 更新视图等, 方便于调试工具查看变化)。
actions则负责进行异步操作。里面的方法是异步的。

流程如下图所示。异步修改和同步修改的流程如下。
在这里插入图片描述

7.2 store中定义actions

7.2.1 语法

// ....
const store = new Vuex.Store({// ...mutations: {addCount(state, num) {state.count += num}},actions: {addCountAsync(context, num) {// 1秒后调用mutations中的addCount方法setTimeout(() => {context.commit('addCount', num)}, 1000)}}// ...
})
  1. actions中的方法,
    • 第一个参数是context 上下文属性,
      • 包含了 state(上面的state),
        commit(用于调用mutations中的方法),
        dispatch(用于调用actions中的方法),
        getters(后面讲),
        rootState, rootGetters
    • 第二个参数是payload(传递)载荷 用于传递参数
      • 注意:payload(传递)载荷只能有一个,想要传递多个参数要使用对象或者数组的形式
  2. actions中的方法, 写异步方法

7.2.2 代码:修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,title: 'hello world'},// mutations 修改state中的数据, 类似于vue组件中的methodsmutations: {// mutations中的方法, //    第一个参数是当前store的state属性//    第二个参数是payload(传递)载荷  用于传递参数//      注意:payload(传递)载荷只能有一个,想要传递多个参数要使用对象或者数组的形式// mutations中的方法, 必须是同步方法// 传单个参数addCount(state, num) {state.count += num},// 传对象subCount(state, obj) {state.count -= obj.numconsole.log(obj.name);}},// actions 类似于mutations, 但是actions中可以写异步方法actions: {// actions中的方法, //    第一个参数是context 上下文属性, //       包含了 state(上面的state), //              commit(用于调用mutations中的方法), //              dispatch(用于调用actions中的方法),//              getters(后面讲), //              rootState, rootGetters//    第二个参数是payload(传递)载荷  用于传递参数//       注意:payload(传递)载荷只能有一个,想要传递多个参数要使用对象或者数组的形式// actions中的方法, 写异步方法addCountAsync(context, num) {// console.log(context);// 1秒后调用mutations中的addCount方法setTimeout(() => {context.commit('addCount', num)}, 1000)},subCountAsync(context, obj) {// 1秒后调用mutations中的subCount方法setTimeout(() => {context.commit('subCount', obj);}, 1000)}}})
export default store

7.3 组件中使用$store.dispatch()调用actions的方法

7.3.1 语法

<template><div><!-- $store.dispatch调用actions中的方法 --><button @click="$store.dispatch('addCountAsync', 2)">1秒后值 + 2</button><button @click="handleAddAsync()">1秒后值 - 2</button></div>
</template><script>
export default {methods: {handleAddAsync() {this.$store.dispatch('subCountAsync', {num: 2, name: '李四'})}}
}
</script>

7.3.2 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子组件 使用原始方式获取</h2><!-- 模板中使用 --><h4>从vuex中获取count的值:{{$store.state.count}}</h4><!-- 组件逻辑中使用 --><h4>从vuex中获取title的值:{{title}}</h4><br><button @click="handleAdd">值 + 1</button><button @click="$store.commit('addCount', 2)">值 + 2</button><button @click="handleSub">值 - 1</button><!-- $store.dispatch调用actions中的方法 --><button @click="$store.dispatch('addCountAsync', 2)">1秒后值 + 2</button><button @click="handleAddAsync()">1秒后值 - 2</button></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {this.$store.commit('addCount', 1)},handleSub() {this.$store.commit('subCount', {num: 1, name: '张三'})},handleAddAsync() {this.$store.dispatch('subCountAsync', {num: 2, name: '李四'})}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

7.3.3 运行结果

在这里插入图片描述

7.4 组件中使用mapActions调用actions的方法

7.4.1 mapActions语法

<template><div></div>
</template><script>
export default {}
</script>

7.4.2 代码实现

<template><div class="box"><h2>Son2 子组件 使用辅助函数方式获取</h2><h4>从vuex中获取count的值:{{count}}</h4><h4>从vuex中获取title的值:{{title}}</h4><br /><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button><!-- mapActions辅助函数调用actions中的方法 --><button @click="addCountAsync(1)">一秒后值 + 1</button><button @click="subCountAsync({num: 1, name: 'hello'})">一秒后值 - 1</button></div>
</template><script>
// 引入 mapState 辅助函数
import { mapState,mapMutations, mapActions} from "vuex";
export default {name: 'Son2Com',methods: {...mapMutations(["addCount","subCount"]),...mapActions(["addCountAsync","subCountAsync"]),// 等价于// addCountAsync () {//   this.$store.dispatch("addCountAsync", 1);// }// subCountAsync () {//   this.$store.dispatch("subCountAsync",{num: 1, name: 'hello'});// }},computed: {...mapState(["count", "title"]),},
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

7.4.3 运行结果

在这里插入图片描述

八、核心概念-getters

8.1 概念getters

除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters。
应用1:state中定义了list,为 1-10 的数组,组件中,需要显示所有大于5的数据。当state中的数据修改后,会影响getters中的属性。
应用2:计算购物车的总价格。
在这里插入图片描述

8.2 store中定义getters

8.2.1 语法

// ....
const store = new Vuex.Store({// ...state: {items: [ // 商品数组{ id: 1, name: "iPhone", price: 5000, quantity: 2 },{ id: 2, name: "MacBook", price: 12000, quantity: 1 }]},mutations: {// 添加商品addItem(state, item) {state.items.push(item)},// 删除商品removeItem(state, id) {state.items = state.items.filter(item => item.id !== id)}},// getters 用来获取state中的数据, 类似于vue组件中的computedgetters: {// getters中的方法, //    第一个参数是state属性//    第二个参数是getters属性// getters中的方法, 必须是同步方法// 计算items数组中所有商品的总价格totalPrice: (state) => {return state.items.reduce((total, item) => {return total + item.price * item.quantity;}, 0).toFixed(2); // 保留两位小数},// 计算items数组中所有商品的平均价格averagePrice: (state, getters) => getters.totalPrice / state.items.length}})// ...

8.2.2 代码:修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,title: 'hello world',items: [ // 商品数组{ id: 1, name: "iPhone", price: 5000, quantity: 2 },{ id: 2, name: "MacBook", price: 12000, quantity: 1 }]},mutations: {addCount(state, num) {state.count += num},subCount(state, obj) {state.count -= obj.numconsole.log(obj.name);},// 添加商品addItem(state, item) {state.items.push(item)},// 删除商品removeItem(state, id) {state.items = state.items.filter(item => item.id !== id)}},actions: {addCountAsync(context, num) {setTimeout(() => {context.commit('addCount', num)}, 1000)},subCountAsync(context, obj) {setTimeout(() => {context.commit('subCount', obj);}, 1000)},},// getters 用来获取state中的数据, 类似于vue组件中的computedgetters: {// getters中的方法, //    第一个参数是state属性//    第二个参数是getters属性// getters中的方法, 必须是同步方法// 计算items数组中所有商品的总价格totalPrice: (state) => {return state.items.reduce((total, item) => {return total + item.price * item.quantity;}, 0).toFixed(2); // 保留两位小数},// 计算items数组中所有商品的平均价格averagePrice: (state, getters) => getters.totalPrice / state.items.length}})export default store

8.3 组件中使用$store.commit调用getters的方法

8.3.1 语法

<template><div class="box"><!-- 在js中要加this进行调用,即this.$store.getters.totalPrice --><h4>从vuex中获取items的值:{{$store.state.items}}</h4><button @click="$store.commit('addItem', {id: 3, name: 'AirPods', price: 1000, quantity: 1})">添加商品</button><button @click="$store.commit('removeItem', 1)">删除商品</button><br><h4>从vuex中获取items的总价格:{{$store.getters.totalPrice}}</h4><h4>从vuex中获取items的平均价格:{{$store.getters.averagePrice}}</h4></div>
</template>

8.3.2 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子组件 使用原始方式获取</h2><!-- 模板中使用 --><h4>从vuex中获取count的值:{{$store.state.count}}</h4><!-- 组件逻辑中使用 --><h4>从vuex中获取title的值:{{title}}</h4><br><button @click="handleAdd">值 + 1</button><button @click="$store.commit('addCount', 2)">值 + 2</button><button @click="handleSub">值 - 1</button><!-- $store.dispatch调用actions中的方法 --><button @click="$store.dispatch('addCountAsync', 2)">1秒后值 + 2</button><button @click="handleAddAsync()">1秒后值 - 2</button><br><h4>从vuex中获取items的值:{{$store.state.items}}</h4><button @click="$store.commit('addItem', {id: 3, name: 'AirPods', price: 1000, quantity: 1})">添加商品</button><button @click="$store.commit('removeItem', 1)">删除商品</button><br><h4>从vuex中获取items的总价格:{{$store.getters.totalPrice}}</h4><h4>从vuex中获取items的平均价格:{{$store.getters.averagePrice}}</h4></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {this.$store.commit('addCount', 1)},handleSub() {this.$store.commit('subCount', {num: 1, name: '张三'})},handleAddAsync() {this.$store.dispatch('subCountAsync', {num: 2, name: '李四'})}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

8.3.3 运行结果

在这里插入图片描述

8.4 组件中使用mapGetters调用getters的方法

8.4.1 mapGetters语法

<template><div class="box"><h4>{{items}}</h4><!-- 这里参数太长 我创建addhandle添加商品 --><button @click="addhandle()">添加商品</button><button @click="removeItem(1)">删除商品</button><br /><h4>从vuex中获取items数组中所有商品的总价格:{{totalPrice}}</h4><h4>从vuex中获取items数组中所有商品的平均价格:{{averagePrice}}</h4></div>
</template><script>
// 引入 mapState 辅助函数
import { mapState,mapMutations, mapActions, mapGetters} from "vuex";
export default {name: 'Son2Com',computed: {// 将items数组中的数据映射到当前组件中...mapState(["items"]),// getters 用来获取state中的数据, 类似于vue组件中的computed...mapGetters(["totalPrice", "averagePrice"]),},methods: {// 将 添加商品 和 删除商品 引入。...mapMutations(["addItem","removeItem"]),// 添加商品addhandle() {this.addItem({id: 3, name: 'AirPods', price: 1000, quantity: 1});}}}
</script>

8.4.2 代码实现

<template><div class="box"><h2>Son2 子组件 使用辅助函数方式获取</h2><h4>从vuex中获取count的值:{{count}}</h4><h4>从vuex中获取title的值:{{title}}</h4><br /><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button><!-- mapActions辅助函数调用actions中的方法 --><button @click="addCountAsync(1)">一秒后值 + 1</button><button @click="subCountAsync({num: 1, name: 'hello'})">一秒后值 - 1</button><br /><h4>{{items}}</h4><!-- 这里参数太长 我创建addhandle添加商品 --><button @click="addhandle()">添加商品</button><button @click="removeItem(1)">删除商品</button><br /><h4>从vuex中获取items数组中所有商品的总价格:{{totalPrice}}</h4><h4>从vuex中获取items数组中所有商品的平均价格:{{averagePrice}}</h4></div>
</template><script>
// 引入 mapState 辅助函数
import { mapState,mapMutations, mapActions, mapGetters} from "vuex";
export default {name: 'Son2Com',computed: {// 将items数组中的数据映射到当前组件中...mapState(["count", "title", "items"]),// getters 用来获取state中的数据, 类似于vue组件中的computed...mapGetters(["totalPrice", "averagePrice"]),},methods: {// 将 添加商品 和 删除商品 引入。...mapMutations(["addCount","subCount","addItem","removeItem"]),...mapActions(["addCountAsync","subCountAsync"]),// 添加商品addhandle() {this.addItem({id: 3, name: 'AirPods', price: 1000, quantity: 1});}}}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

8.4.3 运行结果

在这里插入图片描述

9 前面四个属性的总结

在这里插入图片描述

十、核心概念 - 模块 module

10.1 概念

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

这句话的意思是,如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护

由此,又有了Vuex的模块化在这里插入图片描述

10.2 模块定义

定义两个模块 usersetting。这两个模块分别是用户信息和设置信息。

10.2.1 新建src/store/modules/user.js

user中管理用户的信息状态

const state = {userInfo: {name: 'zs',age: 18}
}const mutations = {}const actions = {}const getters = {}export default {state,mutations,actions,getters
}

10.2.2 新建src/store/modules/setting.js

setting中管理项目应用的 主题色 theme,描述 desc

const state = {theme: 'dark',desc: '描述真呀真不错'
}const mutations = {}const actions = {}const getters = {}export default {state,mutations,actions,getters
}

10.2.3 修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import setting from './modules/setting'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,},mutations: {},actions: {},getters: {},modules: {user,setting}})export default store

10.2.4 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子组件 使用原始方式获取</h2></div>
</template><script>
export default {computed: {},methods: {}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

10.2.5 修改src/components/Son2.vue

<template><div class="box"><h2>Son2 子组件 使用辅助函数方式获取</h2></div>
</template><script>
export default {computed: {},methods: {},
};
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

10.2.6 运行结果如下

在这里插入图片描述

10.3 命名空间

10.3.1 什么是命名空间

我们知道上面虽然都分模块了,但是他们都还是会挂到根级别的state、getters、mutations、actions下。

如果我的user模块和setting模块下的state下都有一个叫做aa的属性。此时我使用辅助函数调用这个属性mapState(['aa']),代码无法识别这个aa是user模块下的aa属性 还是setting模块下的aa属性。
在这里插入图片描述

开启命名空间
解决不同模块的state、getters、mutations、actions重名问题
一般命名空间都是开启的

10.3.2 如何在子模块中开启命名空间

const state = {userInfo: {name: 'zs',age: 18}
}const mutations = {}const actions = {}const getters = {}export default {// 开启命名空间// 1. 解决不同模块命名冲突// 2. 解决不同模块的state、getters、mutations、actions重名问题namespaced: true,state,mutations,actions,getters
}

10.4 分模块的state使用和获取

尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的 state 中,属性名就是模块名使用模块中的数据
在这里插入图片描述
① 直接通过模块名访问 $store.state.模块名.xxx
② 通过 mapState 映射
默认根级别的映射 mapState([ 'xxx' ])
子模块的映射 mapState('模块名', ['xxx','xxx'...]) - 需要开启命名空间

10.5 分模块的mutations使用和获取

注意:默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。

调用子模块中 mutation:
① 直接通过 store 调用 $store.commit('模块名/xxx', 额外参数)
② 通过 mapMutations 映射
默认根级别的映射 mapMutations([ 'xxx' ])
子模块的映射 mapMutations('模块名', ['xxx','xxx'...]) - 需要开启命名空间

10.6 分模块的actions使用和获取

注意:默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。

调用子模块中 action :
① 直接通过 store 调用 $store.dispatch('模块名/xxx ', 额外参数)
② 通过 mapActions 映射
默认根级别的映射 mapActions([ ‘xxx’ ])
子模块的映射 mapActions(‘模块名’, [‘xxx’,‘xxx’]) - 需要开启命名空间

10.7 分模块的getters使用和获取

使用模块中 getters 中的数据:
① 直接通过模块名访问 $store.getters['模块名/xxx']
注意:没使用模块之前是使用的 $store.getters.xxx。
注意:使用模块后不使用的 $store.getters.某块名.xxx,原因为这里是

this.$store.getters的值为
{主模块名:属性字模块名/xxx: 属性
}
// 我们$store.getters.字模块名/xxx会报错因为有 / 这个图书字符。
// 因此使用$store.getters['模块名/xxx']

② 通过 mapGetters 映射
默认根级别的映射 mapGetters([ 'xxx' ])
子模块的映射 mapGetters('模块名', ['xxx','xxx'...]) - 需要开启命名空间

10.8 代码演示

修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子组件 使用原始方式获取</h2><h4>$store.state.user: {{$store.state.user}}</h4><button @click="$store.commit('user/updateName', '李四')">修改名字</button><button @click="$store.dispatch('user/updateNameAsync', '王五')">1秒后修改</button><button @click="$store.commit('user/updateAge', 10)">年龄加10</button><h4>$store.getters["user/ageAddTen"]: {{$store.getters["user/ageAddTen"]}}</h4></div>
</template><script>
export default {computed: {},methods: {},mounted() {}}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

在这里插入图片描述

修改src/components/Son2.vue

<template><div class="box"><h2>Son2 子组件 使用辅助函数方式获取</h2><h4>theme的值为: {{theme}}</h4><h4>desc的值为: {{desc }}</h4><button @click="updateTheme('light')">修改背景色</button><button @click="updateThemeAsync('blue')">一秒后修改背景色</button><h4>desc+theme的值为:{{ themeDesc }}</h4></div>
</template><script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {computed: {...mapState('setting',["desc", "theme"]),...mapGetters('setting',["themeDesc"]),},methods: {...mapMutations('setting',["updateTheme"]),...mapActions('setting',["updateThemeAsync"]),}
};
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

运行结果
在这里插入图片描述

总结

流程图

在这里插入图片描述

不使用分模块的写法

在这里插入图片描述

使用分模块写法

在这里插入图片描述

开启严格模式

在Vuex的根节点文件src/store/index.js中开启。

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import setting from './modules/setting'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: { },mutations: {},actions: {},getters: {},modules: {user,setting}})
export default store

开启命名空间

在子模块src/store/modules/模块.js中开启。

const state = {}const mutations = {}const actions = {}const getters = {}export default {// 开启命名空间namespaced: true,state,mutations,actions,getters
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97664.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97664.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025具身智能赛道观察:技术、产业与视频基础设施

引言 2025 年&#xff0c;具身智能&#xff08;Embodied Intelligence&#xff09;毫无疑问已经成为全球资本追逐的“风口赛道”。从人形机器人、无人配送&#xff0c;到低空经济和智能驾驶&#xff0c;几乎所有与物理世界深度结合的领域&#xff0c;都被纳入具身智能的广义范…

【商业银行风控模型(python版本,实操合集,附带anaconda安装教程,持续更新)】

Anaconda&#xff08;Python工具&#xff09;安装1.Mac中安装Anaconda2.点击“Free Download”下载后&#xff0c;点击“Skip registration”&#xff0c;跳过注册环节。 3.conda list4.安装完成Anaconda基本操作命令 # 查看当前虚拟环境下的所有包 conda list # 查看某个特定的…

FPGA DDR 地址映射-黄金法则

FPGA 中 DDR 控制器的地址映射顺序&#xff08;Address Mapping Order&#xff09; 是优化设计速度&#xff08;带宽和效率&#xff09; 的关键。简单来说&#xff0c;地址映射顺序决定了线性地址如何映射到 DDR 芯片内部的物理结构&#xff08;Bank、Row、Column&#xff09;。…

网络安全设备监控指标

网络安全设备监控指标 近日看到一篇设备情况汇报&#xff0c;内容写得有些欠缺&#xff0c;因此我特意问了一下AI&#xff0c;整理了一下思路。以下是监控需要关注的性能指标。权当抛砖引玉。根据指标可以做监控&#xff0c;也可以做调研指标。 业务承载能力 吞吐量&#xff08…

JSP程序设计之JSP指令

1、JSP指令概念与分类 &#xff08;1&#xff09;概念 JSP指令相当于在编译期间的命令&#xff0c;用来设置与整个JSP页面相关的属性&#xff0c;它并不直接产生任何可见的输出&#xff0c;用来设置全局变量、声明类、要实现的方法和输出内容的类型等。在JSP文件被解析为Java…

Generative Art with p5.js: Creating Beauty from Code

Are you ready to make something truly beautiful with p5.js? Forget about boring bar charts and sales data—let’s create art that moves, breathes, and responds to your touch. We’re going to explore generative art, where code becomes your paintbrush and a…

Wi-Fi技术——网络安全

一、数据帧的安全 1、无线网络安全的发展 理论上无线电波范围内的任何一个站点都可以监听并登录无线网络&#xff0c;所有发送或接收的数据&#xff0c;都有可能被截取&#xff0c;因此无线网络安全十分重要。 原始802.11的安全策略为WEP&#xff0c;其存在根本性的漏洞&#x…

Java提供高效后端支撑,Vue呈现直观交互界面,共同打造的MES管理系统,含完整可运行源码,实现生产计划、执行、追溯一站式管理,提升制造执行效率

前言在当今竞争激烈的制造业环境中&#xff0c;企业面临着提高生产效率、降低成本、保证产品质量以及快速响应市场变化等多重挑战。制造执行系统&#xff08;MES&#xff0c;Manufacturing Execution System&#xff09;作为连接企业上层计划管理系统&#xff08;如ERP&#xf…

【macOS】垃圾箱中文件无法清理的常规方法

【macOS】垃圾箱中文件无法清理的方法如果外接 SSD 移动盘上的垃圾文件无法删除&#xff0c; 可能是由于文件系统格式不兼容、文件被占用、权限不足等原因导致的&#xff0c; 以下是一些常见的解决方法&#xff1a;检查移动硬盘文件系统格式&#xff1a;如果移动硬盘是 NTFS 格…

鸿蒙ArkTS 核心篇-15-条件渲染(组件)

目录 根据逻辑条件结果&#xff0c;渲染不同的 UI 内容 DevEco Studio代码实战 预览效果 总结 根据逻辑条件结果&#xff0c;渲染不同的 UI 内容 DevEco Studio代码实战 let num: number 20Entry Component struct Index {build() {Column() {if (num 1) {Text(文本 1)} …

大模型微调显存内存节约方法

大模型微调时节约显存和内存是一个至关重要的话题&#xff0c;尤其是在消费级GPU&#xff08;如RTX 3090/4090&#xff09;或资源有限的云实例上。下面我将从显存&#xff08;GPU Memory&#xff09; 和内存&#xff08;CPU Memory&#xff09; 两个方面&#xff0c;为你系统地…

Linux笔记12——shell编程基础-6

字符截取命令一、cut命令功能&#xff1a;用于从文件或标准输入中提取指定字段或列语法&#xff1a;cut [选项] 文件名-f&#xff1a;列号&#xff0c;提取第几列&#xff0c;默认识别制表符分割出来的列&#xff08;列号之间用,隔开&#xff09;-d&#xff1a;分隔符&#xff…

高效浏览器标签页管理:Chrome扩展开发完全指南

Hi&#xff0c;我是前端人类学&#xff08;之前叫布兰妮甜&#xff09;&#xff01; 在信息过载的时代&#xff0c;浏览器标签页管理已成为提高工作效率的关键技能。本文将介绍如何开发一个功能完整的Chrome扩展&#xff0c;帮助用户高效管理浏览器标签页&#xff0c;并探讨其实…

从 WPF 到 Avalonia 的迁移系列实战篇3:ResourceDictionary资源与样式的差异与迁移技巧

从 WPF 到 Avalonia 的迁移系列实战篇3:ResourceDictionary资源与样式的差异与迁移技巧 我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。 我的gitcode仓库是Avalonia学习项目。 文中主要示例代码均可在仓库中查看&#xff0c;涵盖核心功能实现与优化方案…

基于Springboot的音乐媒体播放及周边产品运营平台(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的音乐媒体播放及周边产品运营平台&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

【项目思维】嵌入式产业链与技术生态

这篇文章深入解析嵌入式产业链与技术生态上下游关系&#xff0c;辅助建立嵌入式工程师职业发展认知。嵌入式行业并不是“写单片机程序”那么简单&#xff0c;而是一个 从芯片设计到系统集成再到最终产品落地 的复杂生态链。理解上下游价值链&#xff0c;有助于你成为系统型工程…

机器学习(讲解)

一、引言&#xff1a;什么是监督学习&#xff1f;监督学习&#xff08;Supervised Learning&#xff09;是机器学习中最基础且应用最广泛的范式之一。其核心思想是利用已标记的数据&#xff08;即输入-输出对&#xff09;训练模型&#xff0c;使其能够对新的、未标记的数据进行…

使用 Bright Data Web Scraper API + Python 高效抓取 Glassdoor 数据:从配置到结构化输出全流程实战

使用 Bright Data Web Scraper API Python 高效抓取 Glassdoor 数据&#xff1a;从配置到结构化输出全流程实战 摘要 本文详细介绍了如何使用 Bright Data 的 Web Scraper API 搭配 Python&#xff0c;实现对 Glassdoor 平台信息的高效抓取。通过 API 请求构建器、反爬机制集成…

Burgan Bank Türkiye 如何借助 Elastic 改造可观测性和安全性

作者&#xff1a;来自 Elastic Jon Ashley, Ido Friedman, Burak Dz Burgan Bank Trkiye Burgan Bank K.P.S.C. 是科威特项目公司 (KIPCO) 集团的子公司&#xff0c;成立于 1977 年&#xff0c;是中东和北非 (MENA) 地区最大的控股集团和重要银行集团之一。 该银行作为客户的解…

LeetCode 165. 比较版本号 - 优雅Java解决方案

文章目录LeetCode 165. 比较版本号 - 优雅Java解决方案题目描述示例分析示例 1示例 2示例 3算法思路Java实现方案方案一&#xff1a;双指针法&#xff08;推荐&#xff09;方案二&#xff1a;优化的单次遍历法可视化执行过程示例&#xff1a;compareVersion("1.2", &…