多组件共享状态集中管理(读、写)
安装
npm i vuex
搭建vuex环境
创建vuex.store
./store/index.js
// 创建Vuex store
import Vue from "vue";
import Vuex from 'vuex'
// 应用vuex插件
Vue.use(Vuex)
// 响应组件中的动作
const actions = {}
// 操作状态数据
const mutations = {}
// 存储数据
const state = {}
// 计算数据
const getters = {}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
创建vm传入store配置
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
// 应用store
store: store,
render: h => h(App),
}).$mount('#app')
- 注,如果在main.js中引入并应用Vuex插件,会报错
vuex.esm.js?17ba:135
Uncaught Error: [vuex] must call Vue.use(Vuex) before creating a store instance.
在./store/index.js中引入并应用即可
使用store管理全局状态
- 创建store
./store/index.js
const actions = {
myAction(context, value) {
console.log('myAction:' + value)
// 调用mutation
setTimeout(() => context.commit('myMutation', value), 1000)
// 调用action
context.dispatch('otherAction', value);
},
otherAction(){}
}
const mutations = {
myMutation(state, value) {
console.log('myMutation:' + value)
state.myMessage = value
}
}
const state = {
myMessage: ''
}
const getters = {
myMessage1(state) {
return state.myMessage.toLowerCase()
}
}
注,如果在actions中直接操作state,vue开发者工具将无法跟踪,如
context.state.myMessage = value
- 使用全局状态数据
./App.vue
<template>
<div id="app">
<HelloWorld/>
<!-- 使用状态数据 -->
<h1>{{$store.state.myMessage}}</h1>
<!-- 使用计算数据 -->
<h3>{{$store.getters.myMessage1}}</h3>
</div>
</template>
- 调用全局操作
./components/HelloWorld.vue
<template>
<div class="hello">
<button @click="onClick">click</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
methods: {
onClick() {
// 通过store调用操作
this.$store.dispatch('myAction', 'HELLO')
// 如果没有网络请求或其他业务逻辑,也可以直接commit调用mutation
this.$store.commit('myMutation', 'WAITING')
}
}
}
</script>
工作流程
- 如果需要异步调用后台API,在actions中处理,将响应结果commit提交给mutations
- mutations负责对state数据进行更新
- 如果不需要与后台交互,组件可以直接调用mutations
在组件上映射store成员
<template>
<div id="app">
<HelloWorld/>
<h1>{{ message }}</h1>
<h3>{{ myMessage1}}</h3>
</div>
</template>
<script>
import {mapState, mapGetters, mapActions, mapMutations} from 'vuex'
export default {
name: 'App',
computed: {
// message() {
// return this.$store.state.myMessage
// },
// myMessage1() {
// return this.$store.getters.myMessage1
// },
// 自动映射为计算属性
...mapState({
message: 'myMessage'
}),
// 如果不改名可以简写如下
...mapGetters(["myMessage1"])
}
methods:{
// callMyAction() {
// this.$store.dispatch('myAction')
// },
// callMyMutation() {
// this.$store.commit('myMutation')
// },
// 映射actions和mutations
...mapActions(['myAction']),
...mapMutations(['myMutation'])
},
}
</script>
模块化
注册模块状态
export default new Vuex.Store({
modules: {
myModule: {
// 启用命名空间索引
namespaced: true,
actions,
mutations,
state,
getters
}
},
actions: {},
mutations: {},
state: {},
getters: {}
})
调用模块
<template>
<div id="app">
<HelloWorld/>
<!-- 绑定模块属性 -->
<h1>{{ myModule.myMessage }}</h1>
<h3>{{ myMessage1 }}</h3>
</div>
</template>
<script>
export default {
computed: {
// 映射整个模块
...mapState(['myModule']),
// 映射模块的属性,需要启用命名空间索引
...mapGetters('myModule',['myMessage1']),
message() {
// 直接读取模块属性
return this.$store.state.myModule.myMessage
},
message1() {
// 直接读取模块计算属性
return this.$store.getters['myModule/myMessage1']()
}
},
methods: {
// 映射模块方法
...mapActions('myModule',['myAction']),
...mapMutations('myModule',['myMutation']),
onClick() {
// 调用映射的方法
this.myAction('HELLO');
// 直接调用模块方法
this.$store.commit('myModule/myMutation','WAITING')
}
}
}
</script>