状态管理bus
创建bus实例
const Bus = new Vue()
挂载到Vue原型上
Vue.prototype.$bus = Bus
Click触发事件
this.$bus.$emit('on-click', 'hello world')
在其他组件监听‘on-click’事件
this.$bus.$on('on-click', msg => { this.message = msg })
Vuex
State
在Vue组件中获得
const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { return this.$store.state.count } } }
通过mapState辅助函数
// 在单独构建的版本中辅助函数为 Vuex.mapState import { mapState } from 'vuex' export default { // ... computed: mapState({ // 箭头函数可使代码更简练 count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count` countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.count + this.localCount } }) }
computed: mapState([ // 映射 this.count 为 store.state.count 'count' ])
对象展开运算符
computed: { localComputed () { /* ... */ }, // 使用对象展开运算符将此对象混入到外部对象中 ...mapState({ // ... }) }
Getter
主要特点会缓存数据,跟Vue计算属性一样,根据依赖数据发生变化才会重新计算
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } })
通过属性访问
computed: { doneTodosCount () { return this.$store.getters.doneTodosCount } }
mapGetter辅助函数
import { mapGetters } from 'vuex' export default { // ... computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ]) } }
mutation
修改Vuex中store状态的唯一方法是提交mutation
同步的
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } } })
store.commit('increment')
提交载荷(payload)
mutations: { increment (state, n) { state.count += n } }
store.commit('increment', 10)
载荷也可以是对象
mutations: { increment (state, payload) { state.count += payload.amount } }
store.commit('increment', { amount: 10 })
对象风格的提交方式
store.commit({ type: 'increment', amount: 10 })
mutations: { increment (state, payload) { state.count += payload.amount } }
Action
提交mutation,而不是更改Vuex中store的状态
异步的
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } })
参数解构
actions: { increment ({ commit }) { commit('increment') } }
触发action
store.dispatch('increment')
参数有两种形式
// 以载荷形式分发 store.dispatch('incrementAsync', { amount: 10 }) // 以对象形式分发 store.dispatch({ type: 'incrementAsync', amount: 10 })
在组件中触发action
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` // `mapActions` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')` }) } }
组合action
Promise
actions: { actionA ({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) } }
store.dispatch('actionA').then(() => { // ... })
async/await
// 假设 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
Module
将Vuex中的store分割成模块
const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态
插件
Vuex的store接受plugins选项,暴力每个mutation的钩子函数,只接收store唯一的参数
export default store => { console.log('store 初始化') store.subscribe((mutation, state) => { // 每次 mutation 之后调用 // mutation 的格式为 { type, payload } console.log(mutation) }) }
const store = new Vuex.Store({ // ... plugins: [myPlugin] })
我们可以实现本地持久化存储,
内置Logger插件
import createLogger from 'vuex/dist/logger' const store = new Vuex.Store({ plugins: [createLogger()] })