在vue中,父子组件通信可以使用props,自定义事件和插槽,但对于两个关系不大的组件进行通信就不会变的复杂,为了更方便管理组件之间的数据交互,提供了一个集中式的管理方案,任何组件都可以按照指定方式进行读取和更改数据。
vue状态管理(vuex):组件与组件之间的状态管理
目录
一、安装vuex
npm install vuex@3.x --save (vue2安装3.x)
二、vuex使用
1、在src目录下store下的index.js中创建仓库
// 1.引入
import Vue from "vue";
import Vuex from 'vuex';
// 2.安装
Vue.use(Vuex);
// 3.创建仓库
const store = new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
getters: {
},
modules: {
}
})
// 4.导出
export default store;
2、创建了仓库需要在入口文件中引入vuex:
import Vue from 'vue'
import App from './App.vue'
// 引入store
import store from './store/index'
Vue.config.productionTip = false
new Vue({
// 挂载到vue实例上
store,
render: h => h(App)
}).$mount('#app')
三、vuex核心(5个)
vuex有五个核心概念:分别是state、mutations、actions、getters、module
1、state
将需要共享的状态(变量), 都放到State中,是计算属性
1.1、定义状态
const store = new Vuex.Store({
state: {
// 定义状态
count: 0
},
mutations: {
},
actions: {
},
getters: {
},
modules: {
}
})
1.2、在组件中访问vuex的state
方法1: 通过$store访问
<div>{{$store.state.count}}</div>
方法2:通过辅助函数的方式
<template>
<div>
<div>{{ count }}</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
// 计算属性放到computed中
computed: {
// mapState: 将全局的状态(数据)映射为当前组件所需要的计算属性
// 计算属性(不需要在data中声明,由计算得来的)的数据跟data中的是一样的,都是响应式的
...mapState(['count']) // 映射count用展开运算符展开
}
}
</script>
2、mutation
用于变更store中数据。是唯一修改state数据的方法。本质是方法,需要触发调用(commit)。
2.1、定义mutation
const store = new Vuex.Store({
state: {
// 定义状态
count: 0
},
mutations: {
add(state) {
// 变更状态, 修改数据
state.count++;
}
},
actions: {
},
getters: {
},
modules: {
}
})
2.2、触发mutation:在组件中触发mutation,commit一个mutation
方法1: this.$store.commit('xx')
<template>
<div>
<button @click="addOne">点击 + 1</button>
<p>{{count}}</p>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
// 计算属性放到computed中
computed: {
...mapState(['count']) // 映射count用展开运算符展开
},
methods: {
addOne() {
// 触发mutation
this.$store.commit('add')
}
}
}
</script>
方法2:使用辅助函数(mapMutations)
映射为当前组件所需要的methods方法
<template>
<div>
<button @click="addOne">点击 + 1</button>
<p>{{ count }}</p>
</div>
</template>
<script>
import { mapState } from 'vuex';
import { mapMutations } from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
// 将需要的mutation映射成当前组件的方法
...mapMutations(['add']), // 数组中写映射的mutation名字
addone() {
this.add();
}
}
}
</script>
3、action
在mutation中不能写异步, 要写异步只能在action中。
注意:action不能直接修改state的值,需要通过提交mutation,再由mutation修改state。
3.1、定义action方法:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
ASYNCADD(state, num) {
state.count += num;
}
},
actions: {
// 异步方法
AsyncAdd(context,num) {
setTimeout(() => {
// context 上下文 相当于new出来的实例对象(Store对象)
console.log(context);
context.commit('ASYNCADD', num)
},1000)
}
},
getters: {
},
modules: {
}
})
可以打印一下context参数:
3.2、触发action
方法1:
通过this.$store.dispatch()方法
<template>
<div>
<button @click="addOne">点击 + 1</button>
<p>{{$store.state.count}}</p>
</div>
</template>
<script>
export default {
methods: {
addOne() {
this.$store.dispatch('AsyncAdd', 1)
}
}
}
</script>
方法2: 辅助函数方式
<template>
<div>
<button @click="addOne">点击 + 1</button>
<p>{{$store.state.count}}</p>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions(['AsyncAdd']),
addOne() {
// 直接调用action方法
this.AsyncAdd(1);
}
}
}
</script>
4、getter
getter用于对store中的数据进行加工处理, 不对store中的数据进行修改。可以用来对state数据进行简化,
类似于vue的计算属性。
4.1、定义getter
定义的getter一定要有返回值
const store = new Vuex.Store({
state: {
count: 2
},
getters: {
doubleNum: (state) => {
return state.count * 2;
}
}
})
4.2、触发getter
方法1: 通过this.$store.getters.xx
<div>{{$store.getters.doubleNum}}</div>
方法2:辅助函数方式
<template>
<div>
<div>{{doubleNum}}</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
// mapGetters: 将全局的getters映射为当前组件所需要的计算属性
...mapGetters(['doubleNum'])
}
}
</script>
5、module
上面写的state、mutation、action、getter都是写在根模块下面的,对面一个项目来说,不同组件需要不同的vuex,如果把逻辑代码都写在一起,不利于维护,可以将不同模块的内容拆分出来。
const store = new Vuex.Store({
modules: {
moduleOne: {
// 开启命名空间 就是真正的分模块了,不是所有都在根模块下面了
namespaced: true, // 让mutations,actions,getters都在当前模块下
state: {
},
mutations: {
},
actions: {
},
getters: {
}
},
moduleTwo: {
state: {
},
mutations: {
},
actions: {
},
getters: {
}
}
}
})
在组件中打印一下this.$store:
下面以城市模块为例
const store = new Vuex.Store({
modules: {
cityModule: {
namespaced: true,
state: {
cityName: '四川',
cityId: '001'
},
mutations: {
changeCity(state, payload) {
state.cityName = payload;
}
},
actions: {
changeCityAsync(context, payload) {
setTimeout(() => {
context.commit('changeCity', payload)
}, 1000)
}
},
getters: {
showCity: (state) => {
return state.cityName + '欢迎你!';
}
}
}
}
})
5.1、模块管理下state的使用
方法1:$store
<div>{{ $store.state.moduleOne.cityName }}</div>
方法2: 辅助函数
用法: ...mapState('模块名称',['模块变量1', '模块变量2'])
import { mapState } from 'vuex'
export default {
computed: {
...mapState('cityModule', ['cityName', 'cityId'])
}
}
5.2、模块管理下mutation的使用
方法1:
用法:this.$store.commit('模块名/mutation名', '值')
<button @click="updataCity">修改城市名</button>
<script>
export const a = {
methods: {
updataCity() {
this.$store.commit('cityModule/changeCity', '合肥')
}
}
}
</script>
方法2:辅助函数
用法: ...mapMutations('模块名称',['mutation名字', 'mutation名字'])
<button @click="updataCity2">修改城市名</button>
<script>
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations('cityModule', ['changeCity']),
updataCity2() {
this.changeCity('上海'); // 直接调用
}
}
}
</script>
5.3、模块管理下action的使用
方法1:
用法:this.$store.dispatch('模块名称/action名字','参数')
<button @click="updataCityAsync">异步 修改城市名</button>
<script>
export default {
methods: {
updataCityAsync() {
this.$store.dispatch('cityModule/changeCityAsync', '北京')
}
}
}
</script>
方法2:辅助函数
用法: ..mapMutations('模块名称',['action名字', 'action名字'])
<button @click="updataCityAsync2">异步 修改城市名</button>
<script>
import { mapActions } from 'vuex'
export default {
...mapActions('cityModule', ['changeCityAsync']),
updataCityAsync2() {
this.changeCityAsync('北京');
}
}
</script>
5.4、模块管理下getter的使用
方法1:
<div>{{ $store.getters['cityModule/showCity'] }}</div>
下面这种写法是错误的:
<div>{{ $store.getters.cityModule/showCity }}</div>
应该在getters下的cityModule/showCity, 但是点语法找不到cityModule/showCity这个属性,因为不能识别” / “,所以有特殊符号的:用” [] “。
方法2:辅助函数
用法:...mapGetters('模块名称',['getter名字', 'getter名字'])
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters('cityModule', ['showCity'])
}
}