Vuex④(多组件共享数据、Vuex模块化+namespace)

news2025/4/7 10:10:16

文章目录

  • 多组件共享数据
    • 代码实现
  • Vuex模块化
    • 总结

多组件共享数据

我们现在想实现这种情况:
在这里插入图片描述

Person组件的总人数就是Person中列表的长度

br上的是Count组件,br下的是Person组件。

我们通过vuex中的state实现一些数据的多组件共享:在这里插入图片描述

代码实现

Person.vue

<template>
	<div>
		<h1>人员列表</h1>
		<h3 style="color:red">Count组件求和为:{{sum}}</h3>
		<input type="text" placeholder="请输入名字" v-model="name">
		<button @click="add">添加</button>
		<ul>
			<li v-for="p in personList" :key="p.id">{{p.name}}</li>
		</ul>
	</div>
</template>

<script>
	import {nanoid} from 'nanoid'
	export default {
		name:'Person',
		data() {
			return {
				name:''
			}
		},
		computed:{
			personList(){
				return this.$store.state.personList
			},
			sum(){
				return this.$store.state.sum
			}
		},
		methods: {
			add(){
				const personObj = {id:nanoid(),name:this.name}
				this.$store.commit('ADD_PERSON',personObj)
				this.name = ''
			}
		},
	}
</script>

注意点:

这里使用了id生成类nanoid,如果要使用先安装包

yarn add nanoid
或者
npm install nanoid

使用方法:

import { nanoid } from 'nanoid'
const person = {name:'张三', age:18}
// 最后用nanoid给它添加一个id
person.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

Count.vue

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<h3>当前求和放大10倍为:{{bigSum}}</h3>
		<h3>我在{{school}},学习{{subject}}</h3>
		<h3 style="color:red">Person组件的总人数是:{{personList.length}}</h3>
		<select v-model.number="n">
			<option value="1">1</option>
			<option value="2">2</option>
			<option value="3">3</option>
		</select>
		<button @click="increment(n)">+</button>
		<button @click="decrement(n)">-</button>
		<button @click="incrementOdd(n)">当前求和为奇数再加</button>
		<button @click="incrementWait(n)">等一等再加</button>
	</div>
</template>

<script>
	import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
	export default {
		name:'Count',
		data() {
			return {
				n:1, //用户选择的数字
			}
		},
		computed:{
			//借助mapState生成计算属性,从state中读取数据。(数组写法)
			...mapState(['sum','school','subject','personList']),
			//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
			...mapGetters(['bigSum'])
		},
		methods: {
			//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
			...mapMutations({increment:'JIA',decrement:'JIAN'}),
			//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
			...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
		},
		mounted() {
			// const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
			// console.log(x)
		},
	}
</script>

<style lang="css">
	button{
		margin-left: 5px;
	}
</style>

store

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
	/* jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, */
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},
	jiaWait(context,value){
		console.log('actions中的jiaWait被调用了')
		setTimeout(()=>{
			context.commit('JIA',value)
		},500)
	}
}
//准备mutations——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state,value){
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	},
	ADD_PERSON(state,value){
		console.log('mutations中的ADD_PERSON被调用了')
		state.personList.unshift(value)
	}
}
//准备state——用于存储数据
const state = {
	sum:0, //当前的和
	school:'尚硅谷',
	subject:'前端',
	personList:[
		{id:'001',name:'张三'}
	]
}
//准备getters——用于将state中的数据进行加工
const getters = {
	bigSum(state){
		return state.sum*10
	}
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
	getters
})

Vuex模块化

我们查看我们前面的代码不难发现一个问题:那就是多个组件的代码都放在了唯一的actions、mutations、state、getters中,我们前面的案例中只涉及到了两个组件,但是如果我们有几百个几千个组件,这些代码全部堆积到一起,会非常的繁杂。所以我们想对他进行一个分类,将各组件的代码分离开来。

原来我们是这样:
在这里插入图片描述

现在我们变成这样:
在这里插入图片描述
每个配置里面都有其各自的actions、mutations、state、getters。

也就是说现在的store结构发生了变化:
在这里插入图片描述

当然这个a,b起的有点随便,我们稍微语义化一下:
在这里插入图片描述

因为接口暴露的形式发生了变化,接下来我们的组件里面就要发生一些变化。

先来看看Count.vue:

原来是这样:
在这里插入图片描述
现在变成了这样:
在这里插入图片描述

还有一种方法:
在这里插入图片描述

最后我们还有最重要的一步:给配置的命名空间打开
在这里插入图片描述
如果我们缺失了这一步,这些map的第一个参数,countAbout、personAbout这些是识别不出来的!

		computed:{
			//借助mapState生成计算属性,从state中读取数据。(数组写法)
			...mapState('countAbout',['sum','school','subject']),
			...mapState('personAbout',['personList']),
			//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
			...mapGetters('countAbout',['bigSum'])
		},
		methods: {
			//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
			...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
			//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
			...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
		},

接下来我们修改Person.vue,这里我们不使用map方法,而是使用原生的方法看看怎么修改:
在这里插入图片描述
我们上面的firstPersonName这样写是因为:
我们原来store里的state是长这样的:
在这里插入图片描述
但是现在我们store里的getters是长这样的:
在这里插入图片描述
也就是他的key变成了这种形式,但是我们在使用的对象的属性的时候如果使用的是.这种语法那么这个/是不能使用的,凭借js语法的特性我们可以使用[]语法去访问它的属性。

在这里插入图片描述

最后我们还可以对最后一次优化,那就是把分类后的代码分文件放置:
在这里插入图片描述

我们来看看这几个文件:

count.js

//求和相关的配置
export default {
	namespaced:true,
	actions:{
		jiaOdd(context,value){
			console.log('actions中的jiaOdd被调用了')
			if(context.state.sum % 2){
				context.commit('JIA',value)
			}
		},
		jiaWait(context,value){
			console.log('actions中的jiaWait被调用了')
			setTimeout(()=>{
				context.commit('JIA',value)
			},500)
		}
	},
	mutations:{
		JIA(state,value){
			console.log('mutations中的JIA被调用了')
			state.sum += value
		},
		JIAN(state,value){
			console.log('mutations中的JIAN被调用了')
			state.sum -= value
		},
	},
	state:{
		sum:0, //当前的和
		school:'尚硅谷',
		subject:'前端',
	},
	getters:{
		bigSum(state){
			return state.sum*10
		}
	},
}

person.js

//人员管理相关的配置
import axios from 'axios'
import { nanoid } from 'nanoid'
export default {
	namespaced:true,
	actions:{
		addPersonWang(context,value){
			if(value.name.indexOf('王') === 0){
				context.commit('ADD_PERSON',value)
			}else{
				alert('添加的人必须姓王!')
			}
		},
		addPersonServer(context){
			axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
				response => {
					context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
				},
				error => {
					alert(error.message)
				}
			)
		}
	},
	mutations:{
		ADD_PERSON(state,value){
			console.log('mutations中的ADD_PERSON被调用了')
			state.personList.unshift(value)
		}
	},
	state:{
		personList:[
			{id:'001',name:'张三'}
		]
	},
	getters:{
		firstPersonName(state){
			return state.personList[0].name
		}
	},
}

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
import countOptions from './count'
import personOptions from './person'
//应用Vuex插件
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
	modules:{
		countAbout:countOptions,
		personAbout:personOptions
	}
})

总结

模块化+命名空间

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

  2. 修改store.js

    const countAbout = {
      namespaced:true,//开启命名空间
      state:{x:1},
      mutations: { ... },
      actions: { ... },
      getters: {
        bigSum(state){
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
      namespaced:true,//开启命名空间
      state:{ ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        countAbout,
        personAbout
      }
    })
    
  3. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  5. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. 开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

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

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

相关文章

第二章STP应用配置

目录 一 生成树 二 生成树算法 三 STP是什么 四 BPDU是什么 五 BPDU的概念 六 生成树基本配置 一 生成树 生成树算法的网桥协议STP(Spanning Tree Protocol) 它通过生成生成树保证一个已知的网桥在网络拓扑中沿一个环动态工作。网桥与其他网桥交换BPDU消息来监测环路&#xf…

使用 hugo oss 搭建个人博客网站

系列文章目录 文章目录系列文章目录前言一、下载hugo二、oss三、域名四、创建博客上传五、发布&#xff0c;上传文章前言 本文主要详解如何用最低的成本搭建个人博客网站 原本我是直接用的github搭建的博客网站&#xff0c;因为免费&#xff0c;但由于github访问很不稳定&…

Python——正则表达式的应用

文章目录前言正则表达式方法re.search方法group方法re.match方法re.findall方法re.finditer方法re.split方法re.sub方法正则表达式的应用前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 正则表达式是字符串处理的有力工具和技术。 使用正在表达式的目的…

多态(polymorphic)

目录 1. 多态的基本介绍 2. 多态实现条件 3. 重写 重写的介绍&#xff1a; 【重写和重载的区别】 动、静态绑定机制 5 向上转型和向下转型 向上转型 向上转型的特点&#xff08;总结&#xff09;&#xff1a; 向下转型 多态的优缺点 多态是Java三大基本特征中最抽象…

【数据结构初阶】数组栈和链式队列的实现

努力真的要贯穿人的一生吗&#xff1f; 你能活成你想要的样子吗&#xff1f; 真的不知道&#xff01; 文章目录一、栈的概念及结构二、栈的实现&#xff08;动态数组栈&#xff09;2.1 挑选实现栈的结构2.2 栈结构的定义2.3 初始化栈销毁栈2.4 入栈出栈2.5 判空取栈顶元素栈元…

Android Studio App开发之循环试图RecyclerView,布局管理器LayoutManager、动态更新循环视图讲解及实战(附源码)

运行有问题或需要全部源码请点赞关注收藏后评论区留言~~~ 一、循环视图RecyclerView 尽管ListView和GridView分别实现了多行单列和多行多列的列表&#xff0c;使用也很简单&#xff0c;可是它们缺少变化&#xff0c;风格也比较呆板&#xff0c;为此Android推出了更灵活多变的循…

CAS:1347750-20-2,NH2-PEG-SH,Amine-PEG-Thiol,氨基-聚乙二醇-巯基供应

1、名称 英文&#xff1a;NH2-PEG-SH&#xff0c;Amine-PEG-Thiol 中文&#xff1a;氨基-聚乙二醇-巯基 2、CAS编号&#xff1a;1347750-20-2 3、所属分类&#xff1a; Amine PEG Thiol PEG 4、分子量&#xff1a;可定制&#xff0c;5000、氨基-聚乙二醇 1000-巯基、1000、…

云计算———虚拟化技术镜像的构建及Harbor的使用(三)

一、容器管理 1.1容器命令 docker ps &#xff1a;查看正在运行的容器 &#xff0c;已经关闭的不能查看 docker ps -a&#xff08;显示所有容器&#xff09; 可以 docker -f rm MyWordPress&#xff1a;-f 强制删除容器 [rootlocalhost ~]# docker ps -a -q #显示所有容器只…

java项目-第127期SpringBoot+vue的智慧养老手表管理系统-java毕业设计_计算机毕业设计

java项目-第127期SpringBootvue的智慧养老手表管理系统-java毕业设计_计算机毕业设计 【源码请到资源专栏下载】 本系统主要是通过智能手表监控老人的日常生活&#xff0c;比如血压、心率、睡眠步数、以及摔倒情况。 共分为两个角色&#xff1a;家长&#xff0c;养老院管理员&a…

有含金量的AI证书

文章目录证书展示企业认证介绍华为认证人工智能工程师课程内容我的总结和资料证书展示 这是华为云的AI认证&#xff1a; 这是阿里云的大数据认证&#xff1a; 企业认证介绍 一般的企业是办不起来认证的&#xff0c;大家肯定都知道的。本文主要介绍华为云的认证&#xff0c…

经典动态规划:最长递增子序列

力扣第300题&#xff1a;[最长递增子序列]&#xff0c;这道题是非常经典的动态规划和二分查找的题目&#xff0c;我们先看dp: 第一种解法&#xff1a;动态规划 我们先看题目的示例1&#xff1a; 输入&#xff1a;nums [10,9,2,5,3,7,101,18] 输出&#xff1a;4 解释&#x…

【MySQL】MySQL数据库锁使用与InnoDB加锁的原理解析(MySQL专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

【Spring】Bean 的作用域和生命周期

文章目录1. Bean 的作用域1.1 通过一个案例来看 Bean 作用域的问题1.2 作用域的定义1.3 Spring Bean 支持的作用域&#xff08;未介绍完全&#xff09;1.4 修改 Bean 的作用域1.5 Bean 执行流程2. Bean 的生命周期2.1 Bean 的生命周期分为以下 5 大部分2.1.1 实例化 Bean&#…

【代码精读】在optee中注册一个中断

快速链接: . 👉👉👉 【代码精读】–Kernel/ATF/optee等-目录👈👈👈 付费专栏-付费课程 【购买须知】:本专栏的视频介绍-----视频👈👈👈概要: 在optee os总如何注册一个中断? 有没有类似于request_irq的程序? 注册了该中断后,是哪里将该中断配置成Secure…

保边滤波之基于测地距离的滤波与局部拉普拉斯滤波

&#xff08;1&#xff09;基于测地距离的滤波 给定图像I及其Hard Mask M&#xff0c;其中M(x)∈{0,1} &#xff0c;M(x)0表示x属于前景&#xff0c;M(x)1表示x属于背景&#xff0c;图像中某点x到前面Hard Mask的测地距离为 &#xff1f;&#xff1f;&#xff1f;d(a,b)表示…

机器学习中的数学原理——最小二乘法

这几天在刷B站的时候&#xff0c;有个深度学习的博主推荐了一本机器学习的书——《白话机器学习的数学》&#xff0c;抱着浅看一下的态度&#xff0c;我花3个大洋从淘宝上找到了这本书的电子版。看了两天我直接吹爆&#xff01;&#xff01;&#xff01;所以这个专栏就分享一下…

《Linux驱动:DMA直接内存访问》

目录一、前言二、DMA传输主体三、S3c2440上的DMA3.1 DMA请求源3.2 DMA状态机3.3 DMA请求模式3.4 DMA服务模式3.5 DMA传输模式3.6 DMA读写数据大小3.7 DMA寄存器3.7.1 DCON寄存器其他几个重要位四、使用DMA4.1 软件触发DMA4.2 硬件源触发DMA一、前言 DMA(Direct Memory Aaccess…

SpringMVC框架中的拦截器

目录 1. 拦截器接口的介绍 2. 拦截器接口中方法的详细介绍 3. 配置拦截器的步骤 4. 多个拦截器的的执行情况 5. 拦截器与过滤器的区别 1. 拦截器接口的介绍 2. 拦截器接口中方法的详细介绍 public class MyInterceptor implements HandlerInterceptor {Overridepublic bo…

Elasticsearch学习--script

一、概念 es1.4-5.0&#xff0c;默认脚本语言是Grovvy es5.0&#xff0c;默认脚本语言是painless 二、简单使用 将price减一 # 将id1的price减一 POST goods/_update/1 {"script": {"source": "ctx._source.price - 1"} }# 简写 POST goods/_…

Cloud Computing之时钟和顺序Time and Ordering

文章目录Total orderImplementation of total orderLinearizabilityFIFO rderImplementation of FIFO-orderHappen-before orderingCausal orderingSummary参考文献&#xff1a;Lamport’s logical clock 这章重点介绍了分布式系统下各种类型的时序&#xff0c;其实在分布式场景…