# Vuex 状态管理
# 状态管理组成
- state: 驱动应用的数据源
- view: 以声明方式 将 state 映射到视图
- actions: 响应在 view 上的用户输入导致的状态变化
# 组件通信方式
# 父子传值: props
<child title="value from parent"></child>
Vue.component('child',{
props: ['title'],
template: '<p> {{ title }} </p>'
})
# 子传父: $emit
// 子组件使用 $emit 发布自定义事件
<button v-on:click="$emit('enlargeText', 0.1)">Large Button</button>
// 父组件
<child v-on:enlargeText="fontsize += $event"></child>
# Event Bus
// eventbus.js
export defalut new Vue()
import bus from './eventbus'
// 使用 $on 订阅
bus.$on('自定义事件', ()=>{})
bus.$on('自定义事件', data => {})
// 使用 $emit 发布
bus.$emit('自定义事件')
bus.$emit('自定义事件', 数据)
# 父通过 ref 获取子组件
// 父组件内容
<child ref="c"></child>
this.$refs.c.value = 'value from ref'
// 子组件
<input v-model="value">
data(){
return{
value:''
}
}
# Vuex
- 专门为 Vue.js 设计的状态管理库
- 采用集中式的方式存储需要共享的数据
- 从使用角度,就是一个 JS 库
- 作用是进行状态管理,解决复杂组件通信,数据共享 应用场景:
- 多个视图依赖于同一状态
- 来自不同视图的行为需要变更同一状态
# 基本结构
// 导入 Vuex
import Vuex from 'vuex'
Vue.use(vuex)
// 注册 Vuex
export default new Vuex.Store({
state:{},
getters:{},
mutations:{},
actions:{},
modules:{}
})
// 注入 $store 到 Vue 实例
import store from './store'
new Vue({
store,
render: h => h(App)
}).$mount('#app')
# State
Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态 使用 mapState 简化 State 在视图中的使用, mapState 返回计算属性
// store
state: {
count: 0,
msg: 'Hello Vuex'
}
// vue中使用
// 1. 通过属性
this.$store.state.count
// 2. 通过辅助函数
import { mapState } from 'vuex'
// 方式一:接收数组参数
// mapState 返回名称为 count 和 msg 的计算属性
computed: {
...mapState(['count', 'msg'])
}
// 方式二:接收对象参数
// 通过传入对象,可以重命名返回的计算属性
computed: {
...mapState({ num: 'count', message: 'msg '})
}
computed: {
...mapState({
num: state => state.count,
message: state => state.msg
})
}
# Getter
Getter 就是 store 中的计算属性, 使用 mapGetter 简化视图中的使用
// store
state: {
msg: 'Hello Vuex'
},
getters: {
reverseMsg(state) {
return state.msg.split('').reverse().join('')
}
}
// vue中使用
// 1. 通过属性访问
this.$store.getters.reverseMsg
// 2. 通过辅助函数
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
...mapGetters(['reverseMsg'])
// 改名
...mapGetters({
reverse: 'reverseMsg'
})
}
}
# Mutation
- 更改 Vuex 的 store 中的状态的唯一方法是 提交 mutation
- mutation 必须是同步函数
// store
mutations: {
increate(state, payload){
state.count += payload
}
}
// vue 中使用
// 1. 使用 commit
this.$store.commit('increate',2)
// 2. 通过辅助函数
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increate'
]),
...mapMutations({
// 将 this.add() 映射为 this.$store.commit('increate',amount)
add: 'increate'
})
}
}
# Action
- Action 提交的是 mutation,而不是直接变更状态
- Action 可以包含任意异步操作
- 通过 store.dispatch 方法触发
// store
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increate(state, payload){
state.count += payload
}
},
actions: {
// 接受一个与 store 实例具有相同方法和属性的 context 对象
increateAsync(context, payload){
setTimeout(()=>{
context.commit('increate', payload)
},200)
}
}
})
// vue 中使用
// 1. 使用 dispatch
this.$store.dispatch('increateAsync', 5)
// 2. 通过辅助函数
import { mapActions } from 'vuex'
export default{
// ...
methods:{
...mapActions(['increateAsync']),
...mapActions({
// 将 this.addAsync 映射为 this.$store.dispatch('increateAsync')
addAsync: 'increateAsync'
})
}
}
# Module
- 将 store 分割成模块, 每个模块拥有自己的 state、 mutation、 action、 getter, 甚至嵌套子模块
// moduleA
const state = {
count: 2
}
const mutations = {
addCount(state, payload){
state.count += payload
}
}
export default{
// 命名空间
namespaced: true,
state,
mutations
}
// store
const store = new Vuex.Store({
modules: { moduleA }
})
// vue 中使用
import { mapState, mapMutations } from 'vuex'
export default{
// ...
computed: {
...mapState('moduleA', ['count'])
},
methods: {
...mapMutations('moduleA', ['addCount'])
}
}
# 插件
- Vuex 插件就是一个函数, 接收 store 作为唯一参数
- Store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子
const myPlugin = store => {
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
// mutation 的格式 {type, payload}
})
}
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
← TypeScript Vue3 Wheel →