【Vue】状态管理模式Vuex

news2024/12/24 8:32:33

数据共享

  • 流程
  • 搭建
  • 变更状态
  • 辅助函数
  • 分割模块

流程

Vuex是一个Vue的状态管理工具,状态就是数据(某个状态在很多个组件来使用 ,多个组件共同维护一份数据)

在这里插入图片描述

搭建

1)Vuex我们在脚手架搭建项目的时候直接搭建好了,所有可以直接用(如果搭建的时候没有选择Vuex,则需要以下步骤)

1.安装:npm install vuex --save

2.在src下创建store文件夹创建index.js文件,内容如下:
	<script>
		import Vue from 'vue'
		import Vuex from 'vuex' // vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
	
		Vue.use(Vuex)
	
		export default new Vuex.Store({
			state: {
				//存储数据
			},
			getters: {
				//获取state中的数据时进行一些计算或过滤处理
			},
			mutations: {
				//同步更改状态
			},
			actions: {
				//处理异步逻辑
			},
			modules: {
				//模块化状态管理
			}
		})
	</script>

3.在main.js中配置:
	 引入:import store from './store'
	 
	 挂载:
			<script>
				new Vue({
					router,
					store,  //创建的共享数据挂载到vue实例,所有组件能够直接从store中获取到全局的数据
					render: h => h(App)
				}).$mount('#app')
			</script>

2)在store/index.js中写入需要共享的数据

state: {
	//数据
	count:9,
}

3)在组件中使用数据

<h2>{{$store.state.count}}</h2>

变更状态

通过页面上的事件触发(1. @click 触发组件中的事件,2. 组件中的事件触发actions,3. actions发起axios请求获取数据,4. 触发mutations中的函数存储state数据,5. 页面上绑定state中的数据)。当组件created页面初始数据的时候,则获取服务器的数据保存到Vuex中,再获取出来到页面中使用

MyVuex.vue

<h2>计数:{{$store.state.count}}</h2>
<button @click="increment"> + </button> 
<button @click="incrementAsync(10)"> 异步+ </button>

<h2>处理后的计数:{{myCount}}</h2>

<ul v-for="item in $store.state.productData">
	<li>{{item.name}}</li>
</ul>
<button @click="getData">在本组件向服务器发起请求获取数据</button>
<button @click="getData2">在actions中向服务器发起请求获取数据</button>

<script>
	// import {mapActions} from 'vuex'
	export default {
		name: "MyVuex",
		computed:{
			myCount: function(){
				return this.$store.getters.getCount;
			}
		},
		methods:{
			increment(){
				this.$store.dispatch("increment",3); //在组件中使用 this.$store.dispatch('方法名',可带参) 来分发到 action
			},
			incrementAsync(n){
				this.$store.dispatch("incrementAsync",n)
			},
			getData2(){
				this.$store.dispatch("getData2")
			}
			//等同于:引入mapActions之后的新写法,它自动就去找了,参数都省的接了,自动映射为 this.$store.dispatch('xxx')
			//...mapActions([ 
			//	'increment',
			//	'incrementAsync'
			//	'getData2'
			//]),
		
			getData() {
				//在这里发起axios请求获取数据(该怎么发怎么发)
				this.$axios({
					method:"get",
					url:"/api/product.do"
				}).then(resp=>{
					//可以拿到服务器返回的数据,并将数据存储到state中
					this.$store.dispatch("saveData",resp.data)
				})
			}
		}
	}
</script>

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios" //因为拿不到所有引进来
Vue.use(Vuex)

export default new Vuex.Store({
    state: { //数据
        count:9, 
        productData:[]
    },
    
    getters: { //getter用于对store中的数据进行加工处理,不会修改store中的数据,只是包装
    	getCount(state){
			return state.count + '月亮'
		}
    },
    
    mutations: {
        increment(state,n){ //依赖注入state
            state.count+=n; //更改state中的数据
        },
        saveData(state,data){
            console.log(data)
            state.productData=data
        }
    },
    
    actions: {
        increment(context,n){ //依赖注入context(一个与store实例具有相同方法和属性的context对象)
            context.commit("increment",n); //使用context.commit("方法名",可带参) 来提交到 mutation
        },
        incrementAsync(ctx,n){ //实现异步调用
            setTimeout(()=>{
                ctx.commit("increment",n)
            },1000)
        },
        saveData(ctx,data){
            ctx.commit("saveData",data)
        },
        async getData2(ctx){
            await axios({ // this.$axios 这里的this指向Vuex对象,而axios绑在全局Vue对象上,这里拿不到所有在这里引入axios
                method:"get",
                url:"/api/product.do"
            }).then(resp=>{
                console.log(resp.data)
                ctx.commit("saveData",resp.data)
            })
        }
    },
    
    modules: { //模块
    
    }
})

辅助函数

mapActions 、mapMutations(将它们全局的函数映射到本组件中),mapState(将全局数据映射为当前组件的计算属性),mapGetters(仅仅是将store中的getter映射到局部计算属性)

import { mapActions,mapMutations,mapState,mapGetters } from 'vuex'

export default {
	methods: {
		...mapActions([
			'increment', //将 this.方法名() 映射为 this.$store.dispatch('方法名')
      		'incrementB' //将 this.incrementBy(参数) 映射为 this.$store.dispatch('incrementBy',参数)
			// ...
    	]),
    	...mapActions({
			add: 'increment' //将 this.add() 映射为 this.$store.dispatch('increment')
			// ...
    	}),
    	...mapMutations([ //写法与mapActions同理,将dispatch方法换成commit方法
    		// ...
    	]),
    	...mapMutations({ 
    		// ...
    	}),
    	// ... 
	},
	
	computed: {
		...mapState([
  			'count' //当映射的计算属性的名称与state的子节点名称相同时,映射 this.count为 this.$store.state.count
			// ...
		]),
		...mapState({
			done:'doneCount' //将 this.done 映射为 this.$store.state.doneCount
			// ...
		}),
		...mapGetters([ //写法与mapState同理,映射为 this.$store.getters.方法名(store中的数据发生变化,getter中的数据也发生变化,存在一个响应关系)
			// ...
		]),
		...mapGetters({ 
			// ...
		}),
		// ...
	}
}

分割模块

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

目录结构:

src/
│
├── store/
│   ├── index.js          # 主Store入口文件,引入并组合所有模块
│   ├── modules/
│   │   ├── xxxxx.js      # xxxxx模块
│   │   ├── xxxxx.js      # xxxxx模块
│   │   └── ...           # 其它模块
│
└── main.js               # 应用主入口,引入并使用Vuex Store

模块化: 使用模块化可以将Store分割为更小、更易管理的部分,每个模块对应应用的一个功能域
命名空间: 在模块化时,启用命名空间可以避免不同模块之间Getters、Actions、Mutations的命名冲突

定义两个模块:modules/carte.jsmodules/product.js

const state={
};
const getters={
};
const mutations={
};
const actions= {
}
export default {  //模块 carte
	namespaced: true, // 启用命名空间(默认挂载到全局,开启后挂载到子模块,若不开启相当于没做模块化)
	state,
	getters,
	mutations,
	actions
}
const state={
};
const getters={
};
const mutations={
};
const actions= {
}
export default {  //模块 product
	namespaced: true, // 启用命名空间(默认挂载到全局,开启后挂载到子模块,若不开启相当于没做模块化)
	state,
	getters,
	mutations,
	actions
}

引入store的子状态模块,并注册到:store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

//引入store的子状态模块
import carte from "@/store/modules/carte";
import myVuex from "@/store/modules/product";

Vue.use(Vuex)

export default new Vuex.Store({
  modules: { //在modules中配置注册子状态文件
    carte,
    product
  }
})

获取模块中的方法和数据

1) 直接访问
$store.state.模块名.需要使用的状态名
$store.getters[‘模块名/方法名’] (额外参数)
$store.commit(‘模块名/方法名’, 额外参数)
$store.dispatch(‘模块名/方法名’, 额外参数)
注意:默认模块中的内容会被挂载到全局,需要开启命名空间,才会挂载到子模块。

<template>
	<div>
		<!-- $store.state.模块名.需要使用的状态名 -->
		<h2>{{$store.state.carte.userInfo.username }}</h2>
		
		<!-- $store.getters['模块名/方法名'] -->
		<h2>{{$store.getters['carte/filterList']}}</h2>
		<h2>{{filterList2}}</h2>
		
		<button @click="changeAge"> 修改年龄 </button> 
		<button @click="changeAge2"> 修改年龄2 </button>
	</div>
</template>

<script>
	export default {
		name: "Carte",
		computed:{
			filterList2: function () {
				return this.$store.getters['carte/filterList2'];
			}
		},
		
		methods:{
			changeAge() {
				// $store.commit('模块名/方法名',额外参数) 
				this.$store.commit('carte/updateAge',20)
			},
			changeAge2() {
				// $store.dispatch('模块名/方法名',额外参数) 
				this.$store.dispatch('carte/updateAge2',25)
			},
		}
	}
</script>

2) 通过 mapXxxx 映射
默认根级别的映射:mapXxxx([‘xxx’])
子模块的映射:mapXxxx(‘模块名’, [‘xxx’]) , 需要开启命名空间 namespaced:true

<template>
	<div>
		<h2>{{ userInfo.username }}</h2>
		<h2>{{ filterList }}</h2>
		<button @click="updateAge(20)"> 修改年龄 </button> 
		<button @click="updateAge2(25)"> 修改年龄2 </button>
	</div>
</template>
 
<script>
	import { mapState , mapGetters , mapActions , mapMutations } from 'vuex'
	
	export default {
		name: "Carte",
		computed:{
			...mapState('carte', ['xxx','userInfo'])
			
			...mapGetters('carte', ['xxxxxx','filterList ','xxx'])
		}
		
		methods:{
			...mapMutations('carte', ['updateAge']),
			...mapMutations('product', ['xxxx','xxx'])
			
			...mapActions('carte', ['xxx','updateAge2','xxxxxx'])
		}
	}
</script>

// 若需要映射不同模块中的state、getters、actions、mutations内容,就分模块映射

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

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

相关文章

面壁带来了小钢炮,MiniCPM3-4B

MiniCPM3-4B 是 MiniCPM 系列的第三代产品。 相比 MiniCPM1.0/MiniCPM2.0&#xff0c;MiniCPM3-4B 拥有更强大、更多用途的技能集&#xff0c;可以实现更广泛的应用。 MiniCPM3-4B 支持函数调用和代码解释器。 有关使用指南&#xff0c;请参阅高级功能。 MiniCPM3-4B 具有 32k …

微擎忘记后台登录用户名和密码怎么办?解决方法

微擎忘记后台登录名和登录密码是很常见的&#xff0c;服务器百科网fwqbk.com告诉你找回后台登录用户名和密码的方法&#xff1a; 一&#xff1a;找回微擎后台用户名 &#xff08;如果只是忘记了后台登录密码&#xff0c;请忽略此步骤&#xff0c;跳转到第二步&#xff09; 通…

博客摘录「 深度学习 | 编码器-解码器网络、seq2seq模型、束搜索算法」2024年9月7日

老师在课上是这样引入的&#xff1a; Sequence to Sequence Learning&#xff1a;两个循环神经网络组成。 红色部分和绿色部分都是RNN。 预测任务就是从一个序列到另一个序列。 第一个序列称之为原序列&#xff0c;第二个序列称为目标序列。两者…

【Windows】解决新版 Edge 浏览器开机自启问题(简单有效)

文章目录 1.前言2.查找资料3.查找方法4.解决办法 参考文章&#xff1a; 解决新版 Edge 浏览器开机自启问题&#xff08;简单有效&#xff09; Edge开机启动如何关闭 1.前言 电脑开机后edge浏览器开机自启动&#xff0c;并且在任务管理器–启动项内可看到edge浏览器&#xff0…

【Python篇】PyQt5 超详细教程——由入门到精通(中篇一)

文章目录 PyQt5入门级超详细教程前言第4部分&#xff1a;事件处理与信号槽机制4.1 什么是信号与槽&#xff1f;4.2 信号与槽的基本用法4.3 信号与槽的基础示例代码详解&#xff1a; 4.4 处理不同的信号代码详解&#xff1a; 4.5 自定义信号与槽代码详解&#xff1a; 4.6 信号槽…

如何部署Vue+Springboot项目

很多同学在项目上线的部署遇到困难&#xff0c;不懂得怎么部署项目&#xff0c;本文将会带大家手把手从前端部署、java部署来教会大家。 如果项目涉及到了docker相关中间件的环境配置&#xff0c;请参看&#xff1a;https://blog.csdn.net/weixin_73195042/article/details/13…

vue3 为组件的 emits 标注类型,defineEmits基于类型的定义的简单理解

1&#xff09;在 <script setup> 中&#xff0c;emit 函数的类型标注也可以通过运行时声明或是类型声明进行。 2&#xff09;基于类型的&#xff1a; const emit defineEmits<{ (e: change, id: number): void (e: update, value: string): void }>() 说明&#x…

STM32 PWM 详解(基于 STM32F429 HAL 库)

目录 前言 一、PWM 简介 二、STM32F429 的 PWM 功能 1.定时器资源 2.PWM 模式 3.PWM原理图 三、使用 HAL 库配置 STM32F429 的 PWM 1.开启时钟 2.配置定时器 3.配置通道 4.启动定时器 5.PWM 占空比的调节 四、应用实例 五、总结 前言 在嵌入式系统开发中&#…

Python的图像算术与逻辑运算详解

一.图像加法运算 图像加法运算主要有两种方法。第一种是调用Numpy库实现&#xff0c;目标图像像素为两张图像的像素之和&#xff1b;第二种是通过OpenCV调用add()函数实现。第二种方法的函数原型如下&#xff1a; dst add(src1, src2[, dst[, mask[, dtype]]]) – src1表示第…

JavaScript使用地理位置 API

前言 在JavaScript中&#xff0c;Geolocation API 是一种用于访问用户地理位置的接口。这个API允许网页应用程序获取用户的位置并提供基于位置的服务。 if (navigator.geolocation)navigator.geolocation.getCurrentPosition(function () {},function () {});这个函数中需要传…

VMware Workstation v17.6 中文注册精简版

VMware Workstation Pro 是一款功能强大的桌面虚拟化软件&#xff0c;它允许用户在单一的物理机器上同时运行多个操作系统。无论是在 Windows 或 Linux 主机上&#xff0c;您都可以轻松创建和运行各种虚拟机&#xff0c;包括 Windows、Linux 以及 BSD。 全新升级&#xff0c;更…

【debug】nvidia-smi:Failed to initialize NVML: Unknown Error

今天用服务器时又突然报错cuda不可用&#xff0c;输入nvidia-smi检查&#xff0c;报错如题。 根据网上搜的原因&#xff0c;可能是因为系统内核自动升级导致与驱动版本不匹配&#xff0c;尝试重启&#xff1a;reboot&#xff0c;报错&#xff1a; 尝试 exit 退出容器再进入&am…

android framework工程师遇到成长瓶颈迷茫怎么办?千里马经验分享

背景 近来有一些framework老司机粉丝朋友发来了一些framework工作中的一些疑问&#xff0c;具体描述如下&#xff1a; 这个同学遇到的问题&#xff0c;其实就是大部分framework开发者工作比较久后遇到的一个上升瓶颈问题。 具体总结有以下几个瓶颈问题 1、framework属于系…

Qt qrc机制

文章目录 0. 前言1. qrc机制2. qrc使用 0. 前言 要设置窗口图标&#xff0c;就需要有图片及其图片所在路径&#xff0c;在本机上可能没什么问题&#xff0c;但是换了一个机器&#xff0c;路径可能不一致或者图片丢失&#xff0c;这就导致图片显示不出来。 Qt引入qrc机制&…

基于springboot+vue实现的农家乐管理系统

基于springbootvue实现的山庄农家乐管理系统前后端分离项目&#xff08;文末查看源码lw&#xff09;4-10 系统角色&#xff1a; 管理员、用户 主要功能&#xff1a; &#xff08;1&#xff09;用户关键功能包含用户注册登陆、个人信息修改、首页、农家乐、美食信息、民宿信息…

Autosar(Davinci) --- 创建一个S/R类型的port(下)

前言: 前面章节我们讲解了S/R类型的Port如何创建,这一章节,我们着重讲一下生成的代码,以及我们如何添加代码让这些门与灯之间的关系产生连接。 一、CtSaDoor.c 在【Rte.c】的【IO_TASK】中我们可以看到,反复的判断Rte_Ev_Cyclic_IO_Task_0_200ms这个条件是否成立,当200…

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRI…

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略&#xff0c;该策略要求请求的域名、协议和端口必须与提供资源的服务相同。…

828华为云征文|部署RedisStack+可视化操作

目录 1.介绍 1.1 什么是华为云Flexus X实例 1.2 什么是Redis Stack ​编辑 2 准备华为云Flexus应用服务器L实例 3 准备docker环境 4 docker 安装 Redis Stack 4.1拉取镜像 4.2 确认镜像 4.3 启动容器 4.4 放行安全组端口 4.5 操作redis 5 docker compose 配置持久 1.…

Vision Transformer(ViT)模型原理及PyTorch逐行实现

Vision Transformer(ViT)模型原理及PyTorch逐行实现 一、TRM模型结构 1.Encoder Position Embedding 注入位置信息Multi-head Self-attention 对各个位置的embedding融合&#xff08;空间融合&#xff09;LayerNorm & ResidualFeedforward Neural Network 对每个位置上单…