Vuex(小白教程)

Vuex是Vue.js应用的状态管理模式,它集中管理组件状态,并确保状态以可预测方式变化。核心概念包括state(状态)、getter(计算属性)、mutation(同步改变状态)、action(处理异步操作)。此外,还介绍了如何使用module进行模块化管理,以及mapState、mapGetters、mapMutations和mapActions等辅助函数的用法。

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

Vuex(状态管理)

Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex的关键词

1.State 状态
2.Getter 获得者
3.Mutation 变化
4.Action 行动
5.Module 模块
6.store 仓库
7.commit 犯;干;
8.dispatch 派遣

基础用法

页面store/index.js(store配置)

// 页面路径:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

const store = new Vuex.Store({
	state: {
        //状态
		count: 1
	},
    getters: {
        //类似计算机属性
		shuxing1: state => {
    		//state :可以访问数据
			return state.count;
        }
		shuxing2: (state, getters)=> {
			//getters:访问其他函数,等同于 store.getters
			return getters.shuxing1;
        }
	},
	mutations:{
        //改变状态的函数放这里,只能同步
        //context.commit('add')或store.commit('add')执行下面函数
		add(state) {
			// 变更状态
			state.count += 2
		}
	},
	actions:{
        //可以异步(一般用来解决异步),用context.commit('add')执行mutations里面的add函数
		addCountAction (context) {
			//在执行累加的时候,会等待两秒才执行
		    setTimeout(function () {
				context.commit('add')
		    }, 2000)
		}
	}
})
export default store

页面 main.js (引入全局store)

// 页面路径:main.js
import Vue from 'vue'
import App from './App'
import store from './store'

Vue.prototype.$store = store

// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
const app = new Vue({
	store,
	...App
})
app.$mount()

其它页面pages/index/index.vue(获取state)

  1. 通过属性访问,需要在根节点注入 store
<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<text>用户名:{{username}}</text>
	</view>
</template>
<script>
	import store from '@/store/index.js';//需要引入store
	export default {
		data() {
			return {}
		},
		computed: {
			username() {
				return store.state.username 
			}
		}
	}
</script>
  1. 在组件中使用,通过 this.$store 访问到 state 里的数据。
<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<text>用户名:{{username}}</text>
	</view>
</template>
<script>
	export default {
		data() {
			return {}
		},
		computed: {
			username() {
				return this.$store.state.username 
			}
		}
	}
</script>

辅助函数

mapState

<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<view>用户名:{{username}}</view>
		<view>年龄:{{age}}</view>
	</view>
</template>
<script>
	import { mapState } from 'vuex'//引入mapState
	export default {
		data() {
			return {}
		},
		computed: mapState({
		    // 从state中拿到数据 箭头函数可使代码更简练
		    username: state => state.username,
			age: state => state.age,
		}) 
	}
</script>

mapGetters

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<view>{{doneTodosCount}}</view>
	</view>
</template>
<script>
	import {mapGetters} from 'vuex' //引入mapGetters
	export default {
		computed: {
			// 使用对象展开运算符将 getter 混入 computed 对象中
			...mapGetters([
				'doneTodos',
				'doneTodosCount',
				// ...
			])
		}
	}
</script>

如果你想将一个 getter 属性另取一个名字,使用对象形式:

<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<view>{{doneCount}}</view>
	</view>
</template>
<script>
	import {mapGetters} from 'vuex' //引入mapGetters
	export default {
		computed: {
			...mapGetters({
			  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
			  doneCount: 'doneTodosCount'
			})
		}
	}
</script>

mapMutations

使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用。

<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<view>数量:{{count}}</view>
		<button @click="add">增加</button>
	</view>
</template>
<script>
	import { mapMutations } from 'vuex'//引入mapMutations
	export default {
		computed: {
			count() {
				return this.$store.state.count
			}
		},
		methods: {
			...mapMutations(['add'])//对象展开运算符直接拿到add
		}
	}
</script>

mapActions

  • mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store
<!-- 页面路径:pages/index/index.vue -->
<template>
	<view>
		<view>数量:{{count }}</view>
		<button @click="addCountAction">增加</button>
	</view>
</template>
<script>
	import { mapActions } from 'vuex'
	export default {
		computed: {
			count() {
				return this.$store.state.count
			}
		},
		methods: {
			...mapActions([
			    'addCountAction', 
				// 将 `this.addCountAction()` 映射为`this.$store.dispatch('addCountAction')`
                // 将 `this.addCountAction(amount)` 映射为`this.$store.dispatch('addCountAction', amount)`
			])
		}
	}
</script>
  • mapActions 也支持传递一个对象:
	methods: {
		...mapActions({
			addCount: 'addCountAction',
			// 将 `this.addCount()` 映射为 `this.$store.dispatch('addCountAction')`
		})
	}

组合 Action

action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?

首先,你需要明白 store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise

	actions: {
		actionA ({ commit }) {
			return new Promise((resolve, reject) => {
				setTimeout(() => {
					commit('someMutation')
					resolve()
				}, 1000)
			})
		}
	}

现在你可以在组件中使用:

	store.dispatch('actionA').then(() => {
		// ...
	})

在另外一个 action 中也可以:

	actions: {
		// ...
		actionB ({ dispatch, commit }) {
			return dispatch('actionA').then(() => {
				commit('someOtherMutation')
			})
		}
	}

最后,如果我们利用 async / await,我们可以如下组合 action

	// 假设 getData() 和 getOtherData() 返回的是 Promise
	actions: {
		async actionA ({ commit }) {
			commit('gotData', await getData())
		},
		async actionB ({ dispatch, commit }) {
			await dispatch('actionA') // 等待 actionA 完成
			commit('gotOtherData', await getOtherData())
		}
	}

一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。

Module

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 statemutationactiongetter、甚至是嵌套子模块——从上至下进行同样方式的分割:

  1. store 文件夹下新建 modules 文件夹,并在下面新建 moduleA.jsmoduleB.js 文件用来存放 vuexmodules 模块。
├── components             # 组件文件夹
    └── myButton 
        └── myButton.vue   # myButton组件
├── pages
    └── index 
	    └── index.vue      # index页面
├── static
├── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    └── modules           # 模块文件夹
        ├── moduleA.js    # 模块moduleA
        └── moduleB.js    # 模块moduleB
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
  1. main.js 文件中引入 store
	// 页面路径:main.js 
	import Vue from 'vue'
	import App from './App'
	import store from './store'

	Vue.prototype.$store = store

	// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
	const app = new Vue({
		store,
		...App
	})
	app.$mount()
  1. 在项目根目录下,新建 store 文件夹,并在下面新建 index.js 文件,作为模块入口,引入各子模块。
	//  页面路径:store/index.js
	import Vue from 'vue'
	import Vuex from 'vuex'

	import moduleA from '@/store/modules/moduleA'
	import moduleB from '@/store/modules/moduleB'

	Vue.use(Vuex)
	export default new Vuex.Store({
		modules:{
			moduleA,moduleB
		}
	})
  1. 子模块 moduleA 页面内容。
// 子模块moduleA路径:store/modules/moduleA.js 
export default {
	state: {
		text:"我是moduleA模块下state.text的值"
	},
	getters: {
		
	},
	mutations: {
		
	},
	actions: { 
		
	}
}
  1. 子模块 moduleB 页面内容。
// 子模块moduleB路径:store/modules/moduleB.js
export default {
	state: {
		timestamp: 1608820295//初始时间戳
	},
	getters: {
		timeString(state) {//时间戳转换后的时间
			var date = new Date(state.timestamp);
			var year = date.getFullYear();
			var mon  = date.getMonth()+1;
			var day  = date.getDate();
			var hours = date.getHours();
			var minu = date.getMinutes();
			var sec = date.getSeconds();
			var trMon = mon<10 ? '0'+mon : mon
			var trDay = day<10 ? '0'+day : day
			return year+'-'+trMon+'-'+trDay+" "+hours+":"+minu+":"+sec;
		}
	},
	mutations: {
		updateTime(state){//更新当前时间戳
			state.timestamp = Date.now()
		}
	},
	actions: {

	}
}
  1. 在页面中引用组件 myButton ,并通过 mapState 读取 state 中的初始数据。
<!-- 页面路径:pages/index/index.vue -->
<template>
	<view class="content">
		<view>{{text}}</view>
		<view>时间戳:{{timestamp}}</view>
		<view>当前时间:{{timeString}}</view>
		<myButton></myButton>
	</view>
</template>
<script>
	import {mapState,mapGetters} from 'vuex' 
	export default {
		computed: {
			...mapState({
				text: state => state.moduleA.text,
				timestamp: state => state.moduleB.timestamp
			}),
			...mapGetters([
				'timeString'
			])
		}
	}
</script>
  1. 在组件 myButton中,通过 mutations 操作刷新当前时间。
<!-- 组件路径:components/myButton/myButton.vue -->
<template>
	<view>
		<button type="default" @click="updateTime">刷新当前时间</button>
	</view>
</template>
<script>
	import {mapMutations} from 'vuex'
	export default {
		data() {
			return {}
		},
		methods: {
			...mapMutations(['updateTime'])
		}
	}
</script>

参考链接

https://uniapp.dcloud.net.cn/tutorial/vue-vuex.html#vuex-%E6%98%AF%E4%BB%80%E4%B9%88

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值