28-vuex

news2024/11/29 2:51:57

vuex

一、vuex

专门在vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

使用场景:

  • 多个组件依赖于同一状态

  • 来自不同组件的行为需要变更同一状态

二、搭建Vuex环境

  1. 创建文件:src/store/index.js
// 用于创建vuex中最核心的store

// 引入vuex
import Vue from 'vue'
import Vuex from 'vuex'

// 使用Vuex插件
Vue.use(Vuex)

// 准备actions,用于响应组件中的动作
const actions = {}

// 准备mutations,用于操作数据(state)
const mutations = {}

// 准备state,用于存储数据
const state = {}

// 创建并暴露store
export default new Vuex.Store({
    actions,  // actions:actions
    mutations,
    state
});
  1. main.js中创建vm时传入store配置项
import Vue from 'vue'
import App from './App.vue'

// 引入store,因为store写的是index.js,所以此处不需要写完整的./store/index.js路径
import store from './store'

new Vue({
  render: h => h(App),
  store,  // 使用vuex插件之后,就可以使用store配置项了
}).$mount('#app')

此时,Vue实例对象vm和所有的组件实例对象vc都可以通过 this.$store获取到store对象,通过store的dispatch('xxx', value)调用actions中配置的方法,通过store的commit('xxx',value)调用mutations中配置的方法,通过state获取到state中配置的具体变量。

Vuex的一般流程为:

  1. 组件中通过 this.$store.dispatch('xxx', value) 调用 actions中配置的方法
  2. actions的方法中,通过context.commit('xxx', value) 调用 mutations中配置的方法
  3. mutations的方法中,对state中的变量进行修改操作

vuex.png

actions可以理解为饭店的服务员:组件调用dispatch告诉actions服务员点菜。服务员可以进行一些判断逻辑,比如客户是否有忌口、厨房是否还有原材料等(发送ajax去菜市场买菜也在这里处理)

mutations可以理解为饭点的厨师:actions中调用commit通知厨师做具体的菜。厨师对state中具体的原材料变量进行处理。

如果actions中没有什么判断逻辑,只是单纯的调用了commit通知厨师,那么就可以组件中通过commit直接通知厨师做菜。

虽然actions中也可以对state进行操作做菜,但是不推荐这么做。因为页面控制台的Vuex监控插件只会监控mutations对state的改变,不会监控actions。

三、示例

在index.js文件编写actions、mutations、state:

// .......

// 准备actions,用于响应组件中的动作
const actions = {
    // context是一个mini版的store,拥有store的dispatch、commit等相关方法
    jia(context, value) {
        context.commit('JIA', value);
    },
    jian(context, value) {
        context.commit('JIAN', value);
    },
    jiaOdd(context, value) {
        if(context.state.sum % 2) {
            context.commit('JIA', value)
        }
    },
    jiaWait(context, value) {
        setTimeout(() => {
            context.commit('JIA', value)
        }, 500);
    },
    
    demo1(context, value) {
        // actions中的方法,可以通过dispatch继续调用其他方法。
        context.dispatch('demo2', value)
    },
    demo2(context,value) {
        context.commit('JIA', value)
    }
}

// 准备mutations,用于操作数据(state)
const mutations = {
    // mutations内部的方法名一般用大写
    JIA(state, value) {
        state.sum += value
    },
    JIAN(state, value) {
        state.sum -= value
    }
}

// 准备state,用于存储数据
const state = {
    sum:0
}

// .........

组件中调用相关方法:

<template>
  <div>
      <!-- 读取Vuex中的数据 -->
      <h2>当前求和为:{{$store.state.sum}}</h2>
      <select v-model.number="n">
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
      </select>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
      <button @click="incrementOdd">当前求和为奇数再加</button>
      <button @click="incrementWait">等一等再加</button>
  </div>
</template>

<script>
export default {
    name:'Count',
    data() {
        return {
            n:1,  // 用户选择的数字
        }
    },
    methods: {
        increment() {
            // this.$store.dispatch('jia', this.n);
            
            // actions中没有其他逻辑,只是调用commit。那么就可以在组件中通过commit直接调用mutations中的方法
            this.$store.commit('JIA', this.n)  
        },
        decrement() {
            // this.$store.dispatch('jian', this.n);
            this.$store.commit('JIAN', this.n)
        },
        incrementOdd() {
            
            // 通过dispatch调用actions中的方法
            this.$store.dispatch('jiaOdd', this.n)
        },
        incrementWait() {
            this.$store.dispatch('jiaWait', this.n)
        }
    },
}
</script>

四、getters

类似于计算属性,位于store中。当state中的数据需要加工后再使用时,可以使用getters加工。

这个属性是非必须的,可以根据需要添加。

示例:

在index.js中配置getters

// 定义getters
const getters = {
    bigSum(state) {  // 可以接收到state
        return state.sum * 10;  // 需要有返回值
    }
}

// 创建并暴露store
export default new Vuex.Store({
    actions, 
    mutations,
    state,
    getters  // 将getters配置到store中 
});

在页面使用getters:

<template>
  <div>
      <h2>当前求和为:{{$store.state.sum}}</h2>
      <!-- 通过$store.getters获取到getters配置的属性 -->
      <h2>当前求和放大10倍为:{{$store.getters.bigSum}}</h2>
  </div>
</template>

五、4个map方法的使用

mapState可以用于帮我们映射state中的数据为计算属性。

mapGetters用于帮我们映射getters中的数据为计算属性。

mapActions用于帮我们生成与actions对话的方法,即包含$store.dispatch(xxx)的函数

mapMutations用于帮我们生成与mutations对话的方法,即包含$store.commit的函数

如果要从state中获取很多属性,直接使用计算属性的写法为:

<template>
  <div>
      <h2>求和:{{he}}</h2>
      <h2>学校:{{xuexiao}}</h2>
      <h2>学科:{{xueke}}</h2>
  </div>
</template>

<script>
export default {
    name:'Count',
    computed: {
        he() {
            return this.$store.state.sum;
        },
        xuexiao() {
            return this.$store.state.school;
        },
        xueke() {
            return this.$store.state.subject;
        }
    }
}
</script>

每次都要写this.$store.state.比较繁琐,可以使用mapState进行简写:

<script>
    // 引入mapState
import {mapState} from 'vuex'

export default {
    name:'Count',
    computed: {
        // mapState是一个对象,需要使用解构语法对其属性进行解构
        // 此时就相当于在计算属性中定义了he、xuexiao、xueke这些计算属性,冒号后面为映射到的state中的属性
        ...mapState({he:'sum', xuexiao:'school', xueke:'subject'})
    }
}
</script>

特别的,如果计算属性和state属性名相同,可以使用数组简写:

<script>
    // 引入mapState
import {mapState} from 'vuex'

export default {
    name:'Count',
    computed: {
        // ...mapState({sum:'sum', school:'school', subject:'subject'})
        // 数组简写
        ...mapState(['sum', 'school', 'subject'])
    }
}
</script>

同样的,如果要获取getters中的属性,可以使用mapGetters进行简写:

<script>
    // 引入mapState、mapGetters
import {mapState,mapGetters} from 'vuex'

export default {
    name:'Count',
    computed: {
        ...mapState(['sum', 'school','subject']),

        // bigSum() {
        //     return this.$store.getters.bigSum
        // }
        // 简写为
        // ...mapGetters({bigSum:'bigSum'})
        // 或者简写为
        ...mapGetters(['bigSum'])
    }
}
</script>

如果要调用actions中的dispatch方法,直接在methods中写法为:

<template>
  <div>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
  </div>
</template>
<script>

export default {
    name:'Count',
    data() {
        return {
            n:1,  
        }
    },
    methods: {
        
        incrementOdd() {
            // 通过dispatch调用actions中的方法
            this.$store.dispatch('jiaOdd', this.n)
        },
        incrementWait() {
            this.$store.dispatch('jiaWait', this.n)
        }
    }
}
</script>

可以使用mapActions简写$store.dispatch

<template>
  <div>
      
      <!-- 使用mapActions时,需要在调用方法时直接将参数传进去 -->
      <button @click="increment(n)">+</button>
      <button @click="decrement(n)">-</button>
  </div>
</template>
<script>

export default {
    name:'Count',
    data() {
        return {
            n:1,  
        }
    },
    methods: {
        ...mapActions({incrementOdd:'jiaOdd', incrementWait:'jiaWait'})  // 对象写法
    }
}
</script>

如果组件中方法名和actions中方法名同名,则在mapActions中同样可以使用数组写法。

同样的,可以使用mapMutations简写$store.commit

<template>
  <div>
      
      <!-- 使用mapMutations时,需要在调用方法时直接将参数传进去 -->
      <button @click="incrementOdd(n)">当前求和为奇数再加</button>
      <button @click="incrementWait(n)">等一等再加</button>
  </div>
</template>
<script>

export default {
    name:'Count',
    data() {
        return {
            n:1,  
        }
    },
    methods: {
        // mapMutations同样有对象写法、数组写法
        ...mapMutations({increment:'JIA', decrement:'JIAN'}),
    }
}
</script>

mapActions和mapMutations使用时,若需要传递参数:需要在模板中绑定事件时传递好参数,否则参数是事件对象。

六、模块化和命名空间

目的:让代码更好维护,让多种数据分类更加明确。

示例:修改store的index.js

// 定义count组件用到的
const countOptiosn = {
    namespaced: true,
    actions: {
        jia(context, value) {
            // console.log('actions的jia调用了', context, value);
            context.commit('JIA', value);
        },
        jian(context, value) {
            context.commit('JIAN', value);
        },
        jiaOdd(context, value) {
            if(context.state.sum % 2) {
                context.commit('JIA', value)
            }
        },
        jiaWait(context, value) {
            setTimeout(() => {
                context.commit('JIA', value)
            }, 500);
        }
    },
    mutations: {
        JIA(state, value) {
            // console.log('mutations的JIA调用了', state, value)
            state.sum += value
        },
        JIAN(state, value) {
            state.sum -= value
        }
    },
    state: {
        sum:0,
        school: '庞各庄小学',
        subject: '数学'
    },
    getters: {
        bigSum(state) {
            return state.sum * 10;
        }
    }
}

// 定义person组件用到的
const personOptions = {
    namespaced: true,
    actions: {
        addLiSi(context, value) {
            if(value.name === '李四') {
                context.commit('addUser', value);
            } else {
                alert('只能输入李四进行添加')
            }
        }
    },
    mutations: {
        addUser(state, value) {
            state.personList.unshift(value);
        }
    },
    state: {
        personList: [{id:'001', name:'张三'}]
    },
    getters: {
    }
}

// 使用Vuex插件
Vue.use(Vuex)


// 创建并暴露store
export default new Vuex.Store({
    
    // 使用modules进行暴露
    modules: {
        countOptions: countOptions,
        personOptions: personOptions
    }
});

在组件中使用map读取命名空间的数据:

export default {
    name:'Count',
    methods: {
        // 调用countOptions命名空间的mutations
        ...mapMutations('countOptions',{increment:'JIA', decrement:'JIAN'}),
        // 调用countOptions命名空间的actions
        ...mapActions('countOptions',{incrementOdd:'jiaOdd', incrementWait:'jiaWait'})
    },
    computed: {
        // 读取countOptions命名空间的state
        ...mapState('countOptions',['sum', 'school','subject']),
        // 读取countOptions命名空间的getters
        ...mapGetters('countOptions',{bigSum:'bigSum'})
    }
}

在组件中直接读取命名空间的数据:

export default {
    name: 'Person',
    data() {
        return {
            name: ''
        }
    },
    computed: {
        personList() {
            // 读取personOptions命名空间的state数据
            return this.$store.state.personOptions.personList;
        },
        countSum() {
            // 读取countOptions命名空间的getters数据
            return this.$store.getters['countOptions/bigSum']
        }
    },
    methods: {
        addUser() {
            // 调用personOptions命名空间的mutations方法
            this.$store.commit('personOptions/addUser', {id:nanoid(), name: this.name});
            this.name = '';
        },
        addLiSi() {
            // 调用personOptions命名空间的actions方法
            this.$store.dispatch('personOptions/addLiSi',{id:nanoid(), name: this.name});
            this.name = '';
        }
    }
}

先赞后看,养成习惯!!!^ _ ^ ❤️ ❤️ ❤️
码字不易,大家的支持就是我的坚持下去的动力。点赞后不要忘了关注我哦!

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

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

相关文章

Java 【数据结构OJ题十道】—— 二叉树篇1

文章目录一、 检查两棵二叉树是否相同二、 另一棵二叉树的子树三、 二叉树的构建及遍历四、序列化二叉树和反序列化二叉树(难)五、二叉树创建字符串六、 二叉树前序非递归遍历实现七、 二叉树中序非递归遍历实现八、 二叉树后序非递归遍历实现九、二叉搜索树中找到两个结点的最…

如何将电脑文件备份到百度网盘

如何将电脑文件备份到百度网盘&#xff1f;说到文件备份&#xff0c;很多小伙伴会将电脑文件备份到移动硬盘或者U盘里&#xff0c;移动硬盘和U盘是比较常见的存储介质&#xff0c;使用和携带起来也是非常方便&#xff0c;因此深受大家的喜欢。除此之外&#xff0c;大家可能还忽…

2023年,IT互联网还有发展前景吗?

不得不说&#xff0c;互联网在整个社会经济发展中扮演着不可或缺的角色&#xff1b;不仅自身的技术具有前沿性&#xff0c;也推动着其他行业进入数字化经济时代&#xff0c;让我们的工作生活变得更加便捷。 在“互联网”时代&#xff0c;每个服务行业都会利用大数据&#xff0…

将自带记事本替换为Notepad2【中文版,带替换文件】

Notepad2是我在寻找一个合适的代码浏览工具的时候发现的&#xff0c;当需要一个用来浏览代码的文本编辑器时候&#xff0c;需要体积小&#xff0c;速度快&#xff0c;语法高亮&#xff0c;解释度高&#xff0c;VsCode作为生产环境已经不适合作为浏览工具了。了解到Notepad2&…

《动手学习深度学习》笔记(二)线性神经网络

三、线性神经网络 3.1 线性回归 3.1.1 介绍 1. 回归是为一个或多个自变量与因变量之间的关系建模的一类方法。而线性回归基于几个简单的假设&#xff1a;① 自变量和因变量关系是线性的&#xff1b;② 允许包含噪声但是噪声遵循正态分布。   2. 训练数据集/训练集&#xff…

算法训练营 day53 动态规划 买卖股票的最佳时机系列2

算法训练营 day53 动态规划 买卖股票的最佳时机系列2 买卖股票的最佳时机III 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。…

软件项目管理知识回顾---网络图

网络图 9.网络图 9.1简介 1.分类 AOA&#xff0c;双代号&#xff0c;ADMAON,PDM&#xff0c;单代号&#xff0c;前导图2.活动的逻辑管理 头到头/尾&#xff0c;尾到头/尾 依赖关系 3.工序 紧前紧后9.2绘制规则 1.两个节点只能一条线。不能是平行线。平行的话就不知道是哪个活动…

LeetCode-93. 复原 IP 地址

目录题目思路回溯法题目来源 93. 复原 IP 地址 题目思路 意识到这是切割问题&#xff0c;切割问题就可以使用回溯搜索法把所有可能性搜出来&#xff0c;和131.分割回文串就十分类似了。 回溯法 1.递归参数 startIndex一定是需要的&#xff0c;因为不能重复分割&#xff0c…

【GeoDjango框架解析】读取矢量数据写入postgis数据库

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 【GeoDjango框架解析】读取矢量数据写入postgis数据库 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录系列…

关于iframe一些通讯的记录(可适用工作流审批,文中有项目实践,欢迎咨询)

一.知识点(1).我们可以通过postMessage(发送方)和onmessage(接收方)这两个HTML5的方法, 来解决跨页面通信问题&#xff0c;或者通过iframe嵌套的不同页面之间的通信a.父页面代码如下<div v-if"src" class"iframe"><iframeref"iframe"id…

Kafka进阶篇-消费者详解Flume消费Kafka原理

简介 由于挺多时候如果不太熟系kafka消费者详细的话&#xff0c;很容易产生问题&#xff0c;所有剖析一定的原理很重要。 Kafka消费者图解 消费方式 消费者总体工作流程 消费者组初始化流程 消费者详细消费流程 消费者重要参数 bootstrap.servers 向 Kafka 集群建立初…

Jackson使用进阶

实现 注解 属性命名 JsonProperty 定义属性序列化时的名称。 JacksonAnnotation public interface JsonProperty {public final static String USE_DEFAULT_NAME "";public final static int INDEX_UNKNOWN -1;//指定属性的名称。String value() default USE_…

2022IDEA搭建springMvc项目

springmvc项目搭建一. 创建maven项目二. Add Framework Support三. 添加依赖并配置maven四. 配置前端控制器DispatcherServlet五. 配置SpringMVC.XML文件六. 创建controller类七. 创建index.html页面八. 查看jar包是否添加九. 配置tomcat&#xff08;重&#xff09;十. springm…

Kafka(7):生产者详解

1 消息发送 1.1 Kafka Java客户端数据生产流程解析 1 首先要构造一个 ProducerRecord 对象,该对象可以声明主题Topic、分区Partition、键 Key以及值 Value,主题和值是必须要声明的,分区和键可以不用指定。 2 调用send() 方法进行消息发送。 3 因为消息要到网络上进行传输…

国产蓝牙耳机什么便宜又好用?学生党平价蓝牙耳机推荐

蓝牙耳机凭借近几年的快速发展&#xff0c;越来越多的品牌、款式出现在人们的日常生活当中。最近看到很多人问&#xff0c;国产蓝牙耳机什么便宜又好用&#xff1f;针对这个问题&#xff0c;我来给大家推荐几款平价蓝牙耳机&#xff0c;很适合学生党&#xff0c;一起来看看吧。…

推荐系统从入门到入门(3)——基于MapReuduce与Spark的分布式推荐系统构建

本系列博客总结了不同框架、不同算法、不同界面的推荐系统&#xff0c;完整阅读需要大量时间&#xff08;又臭又长&#xff09;&#xff0c;建议根据目录选择需要的内容查看&#xff0c;欢迎讨论与指出问题。 目录 系列文章梗概 系列文章目录 三、MapReduce 1.MapReduce详…

赶紧收藏:如何使用Telegram客户支持

想要使用Telegram需要客户支持&#xff1f;您需要了解的有关使用Telegram作为客户服务渠道的所有信息&#xff0c;本文章都会介绍。我们将首先讨论提供Telegram支持以及入门所需了解的内容。然后&#xff0c;我们将向您展示如何用智能客服工具ss可以帮助您提供一流的服务Telegr…

Oracle监听详解

本文摘自《ORACLE数据库技术实用详解》和《成功之路&#xff1a;ORACLE 11g学习笔记》 配置网络环境 本文将介绍和Oracle相关的网络问题&#xff0c;Oracle网络建立在操作系统之上。配置操作系统网络是配置Oracle网络的第一步。在配置Oracle网络之前&#xff0c;我们需要确保操…

数学基础--均值、方差、标准差、协方差

1. 简介 统计学中最核心的概念之一是&#xff1a;标准差及其与其他统计量&#xff08;如方差和均值&#xff09;之间的关系&#xff0c;本文将对标准差这一概念提供直观的视觉解释&#xff0c;在文章的最后我们将会介绍协方差的概念。 2. 概念介绍 均值 均值&#xff1a; 均值…

(一)Spring-Cloud源码分析之核心流程关系及springcloud与springboot包区别(新)

文章目录1. 前言2. springcloud简介3. Springcloud包简介4. Springcloud和Springboot流程关系5. Springcloud启动流程新增的功能和接口5.1 新增接口5.2 新增功能类5.2.1 spring-cloud-context包5.2.2 spring-cloud-commons包6. Springcloud实现机制带来的问题7. Springcloud和S…