(9)vuex组件通信
1. vuex 是什么
(1) github 站点: https://github.com/vuejs/vuex
(2) 在线文档: https://vuex.vuejs.org/zh-cn/
(3) 简单来说: 对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)
2: 多组件共享状态的问题
(1)多个视图依赖于同一状态
(2) 来自不同视图的行为需要变更同一状态
(3) 以前的解决办法
a. 将数据以及操作数据的行为都定义在父组件
b. 将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
(4) vuex 就是用来解决这个问题的
3:vuex 核心概念和 API
(1) state vuex 管理的状态对象
(2) mutations 包含多个直接更新 state 的方法(回调函数)的对象
谁来触发: action 中的 commit('mutation 名称')
只能包含同步的代码, 不能写异步代码
const mutations = {
xx (state, {data1}) {
// 更新 state 的某个属性
}
(1) actions
包含多个事件回调函数的对象
通过执行: commit()来触发 mutation 的调用, 间接更新 state
谁来触发: 组件中: $store.dispatch('action 名称', data1) // 'zzz'
可以包含异步代码(定时器, ajax)
const actions = {
xxx({commit, state}, data1) {
commit('yyy', {data1})
}
}
(4). getters
包含多个计算属性(get)的对象 谁来读取: 组件中: $store.getters.xxx()
使用: //向外暴露Store对象;在main.js中配置
//暴露
export default new Vuex.Store({
state,
mutations,
actions,
getters
}
//配置
import store from './store'
new Vue({
store
})
(1) Store对象
(1) 所有用 vuex 管理的组件中都多了一个属性$store, 它就是一个 store 对象
(2) 属性:
state: 注册的 state 对象
getters: 注册的 getters 对象
(3) 方法:
dispatch(actionName, data): 分发调用 action.
(4) 实践 目录结构App.vue 主组件 ,store.js vuex配置 main.js入口文件配置 Main.js import Vue from 'vue' import App from './App.vue' import store from "./store" /* eslint-disable no-new */ new Vue({ el: '#app', components: {App}, // 映射组件标签 template: '<App/>', // 指定需要渲染到页面的模板 store //再次此处配置 }) // store.js const mutations = { INCREAMENT(){ state.count = state.count +1; }, DECREAMENT(){ state.count = state.count -1; } } /* 包含了n个间接更新状态的方法的对象 */ const actions = { //调用 increament({commit}){ commit("INCREAMENT");//调用增加的方法 }, decreament({commit}){ commit("DECREAMENT"); }, increamentisOdd({commit,state}){ if(state.count%2===1){ commit("DECREAMENT"); } }, increamentasync({commit}){ setInterval(()=>{ commit("INCREAMENT"); },1000) } } /* 包含多个getter计算属性的对象 */ const getters ={ //计算属性 evenOrOdd(state){ return state.count%2===0? "偶数":"奇数" } } export default new Vuex.Store({ state, mutations, actions, getters }) //App.vue <template> <div> <p>click {{count}} time,count is {{evenOrOdd}}</p> <button @click="increament">+</button> <button @click="decreament">-</button> <button @click="increamentisOdd">判断是否是奇数</button> <button @click="increamentasync">异步增加</button> </div> </template> <script> import {mapState, mapGetters, mapActions} from 'vuex' export default { //默认暴露一个模块 data(){ return {} }, computed:{ ...mapState(['count']), ...mapGetters(['evenOrOdd']) }, methods:{ ...mapActions(['increament', 'decreament', 'increamentisOdd', 'increamentasync']) } } </script> <style> </style> //或者 <template> <div> <p>click {{count}} times, count is {{evenOrOdd}}</p> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementIfOdd">increment if odd</button> <button @click="incrementAsync">increment async</button> </div> </template> <script> export default { mounted () { console.log(this.$store) }, computed: { count () { return this.$store.state.count }, evenOrOdd () { return this.$store.getters.evenOrOdd } }, methods: { increment () { this.$store.dispatch('increment') }, decrement () { this.$store.dispatch('decrement') }, incrementIfOdd () { this.$store.dispatch('incrementIfOdd') }, incrementAsync () { this.$store.dispatch('incrementAsync') } } } </script> <style> </style>
(1)实践
目录结构App.vue 主组件,store.js vuex配置 main.js入口文件配置
Main.js
import Vue from 'vue'
import App from './App.vue'
import store from "./store"
/* eslint-disable no-new */
new Vue({
el: '#app',
components: {App}, // 映射组件标签
template: '<App/>', // 指定需要渲染到页面的模板
store //再次此处配置
})
// store.js
const mutations = {
INCREAMENT(){
state.count = state.count +1;
},
DECREAMENT(){
state.count = state.count -1;
}
}
/*
包含了n个间接更新状态的方法的对象
*/
const actions = {
//调用
increament({commit}){
commit("INCREAMENT");//调用增加的方法
},
decreament({commit}){
commit("DECREAMENT");
},
increamentisOdd({commit,state}){
if(state.count%2===1){
commit("DECREAMENT");
}
},
increamentasync({commit}){
setInterval(()=>{
commit("INCREAMENT");
},1000)
}
}
/*
包含多个getter计算属性的对象
*/
const getters ={
//计算属性
evenOrOdd(state){
return state.count%2===0? "偶数":"奇数"
}
}
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
//App.vue
<template>
<div>
<p>click {{count}}
time,count is {{evenOrOdd}}</p>
<button @click="increament">+</button>
<button @click="decreament">-</button>
<button @click="increamentisOdd">判断是否是奇数</button>
<button @click="increamentasync">异步增加</button>
</div>
</template>
<script>
import {mapState, mapGetters, mapActions} from 'vuex'
export default {
//默认暴露一个模块
data(){
return {}
},
computed:{
...mapState(['count']),
...mapGetters(['evenOrOdd'])
},
methods:{
...mapActions(['increament', 'decreament', 'increamentisOdd', 'increamentasync'])
}
}
</script>
<style>
</style>
//或者
<template>
<div>
<p>click {{count}}
times, count is {{evenOrOdd}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">increment if odd</button>
<button @click="incrementAsync">increment async</button>
</div>
</template>
<script>
export default {
mounted () {
console.log(this.$store)
},
computed:
{
count () {
return this.$store.state.count
},
evenOrOdd () {
return this.$store.getters.evenOrOdd
}
},
methods: {
increment () {
this.$store.dispatch('increment')
},
decrement () {
this.$store.dispatch('decrement')
},
incrementIfOdd ()
{
this.$store.dispatch('incrementIfOdd')
},
incrementAsync ()
{
this.$store.dispatch('incrementAsync')
}
}
}
</script>
<style>
</style>