一、Vuex介绍
vuex是状态管理工具,提供数据仓库,用于组件间的数据共享。当使用vuex共享数据时,应遵循单项数据流。
官网地址:Vuex 是什么? | Vuex
状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
以下是一个表示“单向数据流”理念的简单示意:
二、Vuex安装
1. 安装vuex,vue2.x版本使用vuex3,vue3.x使用vuex4
npm环境执行命令 npm i vuex@3 或 npm i vuex@4
npm i vuex@3
yarm环境
yarn add vuex
2. 创建目录,及index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
3. 在main.js文件中挂载store
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App)
}).$mount('#app')
4. 验证,在项目中可以使用$store属性
三、 Vuex核心概念
store的js文件
import Vue from 'vue'
import Vuex from 'vuex'
import setting from './modules/setting.js'
import user from './modules/user.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
data1: 99999,
data2: 88888
},
getters: {
// 包含参数
data1ToString: state => (v1, v2) => {
return state.data1 + '' + v1 + v2
},
// 不包含参数
data2ToString (state) {
return state.data1 + 'string'
},
// 使用getters作为参数
data12 (state, getters) {
return getters.data1ToString('s', 'd') + getters.data2ToString
}
},
mutations: {
changeData1 (state) {
state.data1 = 'hfdd'
},
changeData2 (state, v) {
state.data2 = v
}
},
actions: {
changeData2Sync (context, v) {
setTimeout(() => {
context.commit('changeData2', v)
}, 1000)
}
},
modules: {
setting,
user
}
})
1. state 状态仓库,存储组件共享的所有数据。
使用:在store的js文件中设置状态数据,在组件中使用$store.state.属性名 应用数据
mapState辅助拓展函数,等价于compute中的计算
state: {
data1: 99999,
data2: 88888
},
// SonA.vue
<template>
<div>
<h1>我是子组件A {{ $store.state.data1 }}</h1>
<h1>测试数据 {{ data3 }}</h1>
<h1>测试数据 {{ data2 }}</h1>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
computed: {
data3 () {
return this.$store.state.data2
},
...mapState(['data2', 'data1']), // 等价于changeData2的写法
},
}
</script>
2. mutations,store的状态的唯一提交方法
由于vuex遵循单项数据流规范,所有的状态修改操作均在mutations中执行。同步执行。mutations由type和handle组成。handle函数中state作为第一个参数变量。组件提交事件的时候,可以传递一个参数且只能传递一个参数,作为mutations的载荷(payload),实现动态修改状态功能。当参数有多个时,需要通过数据或对象的方式传送。
mapMutations辅助拓展函数,作用等价于methods中的同名方法,可直接调用。且当methods中存在与...mapMutations中同名的方法时,组件优先使用mapMutations中的方法。
mutations: {
changeData1 (state) {
state.data1 = 'hfdd'
},
changeData2 (state, v) {
state.data2 = v
}
},
// SonV.vue
<template>
<div>
<h1>我是子组件A {{ $store.state.data1 }}</h1>
<button @click="changeData1">修改数据1</button>
<button @click="changeData2(56789)">修改数据2</button>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
methods: {
changeData2 () {
this.$store.commit('changeData1')
},
...mapMutations(['changeData1', 'changeData2']) // 等价于changeData2的写法
}
}
</script>
3. actions(分发),异步操作。
使用方法与mutations类似,handler方法中的第一个参数是context(上下文,未分模块时默认store),通过context.commit('mutations中的方法名')修改属性值。组件中通过store.dispatch触发。其辅助函数为mapActions。
actions: {
changeData2Sync (context, v) {
setTimeout(() => {
context.commit('changeData2', v)
}, 1000)
}
},
// SonV.vue
<template>
<div>
<h1>测试数据 {{ data2 }}</h1>
<button @click="changeData2Sync(676576)">修改数据2-0</button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
methods: {
changeData1Sync () {
this.$store.dispatch('changeData1Sync', '000000')
},
...mapActions(['changeData2Sync']) // 等价于changeData1Sync的写法的写法
}
}
</script>
4. getters,state中派生出来的属性
类似于compute属性,设置state中派生出来的属性值,必须有返回值。在组件中通过$store.getters.属性名 获取值。其辅助函数为mapGetters。
第一个参数是state,可以把getters第二个参数。也可以通过方法的方式传送多个参数。
getters: {
// 包含参数
data1ToString: state => (v1, v2) => {
return state.data1 + '' + v1 + v2
},
// 不包含参数
data2ToString (state) {
return state.data1 + 'string'
},
// 使用getters作为参数
data12 (state, getters) {
return getters.data1ToString('s', 'd') + getters.data2ToString
}
},
// SonV.vue
<template>
<div>
<h1>测试数据 {{ data1ToString('dddddd', 'sssss') }}</h1>
<h1>测试数据 {{ data12 }}</h1>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['data1ToString', 'data2ToString', 'data12'])
}
}
</script>
5.mofules 模块
vuex使用单一状态树,当属性增多时,inedx.js文件会比较巨大,此时分割成多个文件,或便于管理与维护。
建议在模块js中开启命名空间,便于调用。namespaced: true
// index.js store
import Vue from 'vue'
import Vuex from 'vuex'
import setting from './modules/setting.js'
import user from './modules/user.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
setting,
user
}
})
// user.js
const state = {
userInfo: {
name: 'HG',
age: 18
},
group: 'HJ'
}
const mutations = {
changeUser (state, v) {
state.userInfo.name = v
}
}
const actions = {
changeUserSync (context, v) {
setTimeout(() => {
context.commit('changeUser', v)
}, 1000)
}
}
const getters = {
groupEx (state) {
return state.group + 'BJ'
}
}
export default {
namespaced: true, // 开启命名空间,便于辅助函数调用模块中的信息
state,
mutations,
getters,
actions
}
在组件中调用模块中信息方法:
- state: $store.state.模块命名空间.属性名;...mapState('模块命名空间', ['属性名1', '属性名2'])
- getters: $store.getters['模块命名空间/getters属性名'];...mapGetters('模块命名空间', ['getters属性名'])
- mutations: $store.commit['模块命名空间/mutations方法名', '参数'];...mapMutations('模块命名空间', ['mutations方法名'])
- actions: $store.dispatch['模块命名空间/actions方法名', '参数'];...mapActions('模块命名空间', ['actions方法名'])
<template>
<div>
<h1>子模块数据 {{ $store.state.user.userInfo }}</h1>
<h1>子模块数据2 {{ group }}</h1>
<h1>子模块数据groupEx {{ groupEx }}</h1>
<button @click="changemoduleInfo(676576)">修改子模块数据</button>
<button @click="changeUser('errr')">修改子模块数据2</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
computed: {
...mapState('user', ['userInfo', 'group']),
groupEx1 () {
return this.$store.getters['user/groupEx']
},
...mapGetters('user', ['groupEx'])
},
methods: {
changemoduleInfo (v) {
this.$store.commit('user/changeUser', v)
},
...mapMutations('user', ['changeUser']),
changeUserSync1 (v) {
this.$store.dispatch('user/changeUserSync', v)
},
...mapActions('user', ['changeUserSync'])
}
}
</script>