vue组件之间的共享状态:store模式与vuex状态管理

特性

共享状态解决以下问题:

  • 多个组件共享状态state,如兄弟组件之间的状态传递
  • 不同组件行为需要更新同一state,但不破坏组件之间的单向数据流

对于简单应用 store模式

  • 集中式状态管理
  • action统一管理state的更新,更好地记录state的变化和调试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var store = {
debug: true,
state: {
message: 'Hello!'
},
setMessageAction (newValue) {
if (this.debug) console.log('setMessageAction triggered with', newValue)
this.state.message = newValue
},
clearMessageAction () {
if (this.debug) console.log('clearMessageAction triggered')
this.state.message = ''
}
}

// 每个实例/组件仍然可以拥有和管理自己的私有状态
var vmA = new Vue({
data: {
// ... privateState
sharedState: store.state
}
})

对于大型应用 vuex状态管理

  • 全局单例模式管理状态
  • 集中式存储管理应用的所有组件的状态

store注入根实例,通过this.$store访问

1
2
3
4
5
6
7
8
9
10
11
12
13
// 定义单例store
const store = new Vuex.Store({
mutations: { }, // 全局action
modules: { a: moduleA }
})
// 注入根实例
const app = new Vue({
el: '#app',
store,
components: { Counter },
template: `
<div class="app"></div>`
})

modules分割模块

1
2
3
4
5
6
7
8
9
10
// 定义store模块
const moduleA = {
state: { },
mutations: { },
actions: { }
}

// 引用
this.$store.state.a // -> moduleA 的状态
this.$store.state.b // -> moduleB 的状态

state状态

  • 状态存储state是响应式的
  • 通过commit提交mutation去改变状态
  • 组件可以在计算属性中获取state
    1
    2
    // 引用
    this.$store.state.module.selectState

getter计算属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
// 通过方法访问,并传参
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}

// 引用
this.$store.getters.doneTodos
this.$store.getters.getTodoById(2)

mutation

  • 同步函数
  • mutation中变更state
  • 通过 this.$store.commit(‘funName’) 提交mutation
1
2
3
4
5
6
7
8
// 定义
mutations: {
setFlag (state, params) {
state.count++
}
}
// 调用
this.$store.commit('setFlag', params)

action

  • 异步函数
  • action中提交mutation变更state
  • 通过 this.$store.dispatch() 分发action
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定义
actions: {
funcname (context, params) { // {commit, state}
// context.state
// context.getters
context.commit('setFlag')
},
// 返回promise
funcname2 (context) {
return new Promise((resolve, reject) => {
resolve()
}).then().catch()
}
}
// 调用
this.$store.dispatch('funname', params)
await this.$store.dispatch('funcname2')