Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。如果项目很小,可以不使用vuex
这个状态自管理应用包含以下几个部分:
在一个模块化的打包系统中,您必须显式地通过 Vue.use() 来安装 Vuex:
// 创建一个仓库 src/store/index.js
import Vue from ‘vue‘
import Vuex from ‘vuex‘
Vue.use(Vuex)
export default new Vuex.Stroe({
state: {
count:‘‘,
....
},
actions: {
....
},
mutations: {
...
}
})
通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到
// main.js
import store from ‘./store‘
new Vue({
el: ‘#app‘,
router,
store,
components: { App },
template: ‘<App/>‘
})
通过在根实例中注册store选项后,子组件可以通过this.$store.state.count访问到该状态
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。
为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,
import { mapState } from ‘vuex‘ // => 解构赋值,相当于mapState = vuex.mapState
// 注意: mapState名字不能随便取,因为随便取的话,vuex对象下没有这个方法
computed: {
otherComputed () {/* do something... */},
// 将this.count 映射为 this.$store.state.count
// 将this.city 映射为 this.$store.state.city
...mapState([‘count‘], [‘city‘]),
// 也可以接收一个对象,
// 将this.currentCount 映射为 this.$store.state.count
// 将this.currentCity 映射为 this.$store.state.city
// ...mapState({currentCount: ‘count‘, currentCity: ‘city‘}),
}
// 更改 Vuex 的 store 中的状态(state)的唯一方法是提交 mutation。
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
// store/index.js
export default new Vuex.Stroe({
state: {
count: 0,
},
actions: {
},
mutations: {
increment (state, value) {
state.count = value
},
decrement (state, obj) {
state.count = obj.count--
}
}
})
// 在组件中提交Mutations
- 可以使用this.$store.commit(‘increment‘, 10)方法,第二个参数作为要改变的值,也可以是一个对象
- 对象风格的提交方式, this.$store.commit({type: ‘decrement‘, count: 10})
type属性指定调用mutations对象的方法, 其他属性作为该方法的第二参数的属性
// 使用mapMutations辅助函数提交Mutations
import { mapMutations, mapState } from ‘vuex‘ // 也可以同时引用
export default {,
name: ‘‘,
data () {// do something....},
computed: {...mapState([‘count‘])},
methods: {
otherMethods () {/* do something.... */},
handleIncrementClick () {
this.increment(this.count)
this.incr(this.count)
},
handleDecrementClick () {
this.decrement(this.count)
this.decr(this.count)
},
// 将this.increment()映射为 this.$store.commit(‘increment‘)
// 将this.decrement()映射为 this.$store.commit(‘decrement‘)
...mapMutations([‘increment‘, ‘decrement‘]),
// 对象提交方式
// 将this.incr()映射为 this.$store.commit(‘increment‘)
// 将this.decr()映射为 this.$store.commit(‘decrement‘)
...mapMutations({incr: ‘increment‘, decr: ‘decrement‘})
}
}
// Vuex 的 store 中的状态是响应式的,当我们变更状态时,监视状态的 Vue 组件也会自动更新。
// Mutation 必须是同步函数,一条重要的原则就是要记住 mutation 必须是同步函数
在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。
Action 类似于 mutation,不同在于:
Action 函数接受一个与 store 实例具有相同方法和属性的 **context** 对象,
因此你可以调用 context.commit 提交一个 mutation,
或者通过 context.state 和 context.getters 来获取 state 和 getters。
// store/index.js
export default new Vuex.Stroe({
state: {
count: 0,
},
actions: {
increment (context) {
context.commit(‘increment‘, context.count)
},
// 异步操作
decrementAsync ({ commit }, obj) {
setTimeout(() => {
// 结构赋值, 这里的 commit === commit.commit
// 这里commit保存的是context上下文对象,而他有一个方法叫commit,es6语法键值对都名字一样可以简写
commit(‘decrement‘, obj)
}, 1000);
}
},
mutations: {
increment (state, value) {
state.count = value
},
decrement (state, obj) {
state.count = obj.count--
}
}
})
// 在组件中分发action
- 可以使用this.$store.dispatch(‘increment‘)
- 或者this.$store.dispatch(‘decrementAsync‘, {count: 10}) // 传参对象提交
// 使用mapActions辅助函数
import { mapActions } from ‘vuex‘
export default {
//....
methods: {
otherMethods () {/* do something... */},
handleIncrementClick () {
this.increment()
this.incr()
},
handleDecrementAsyncClick () {
this.decrementAsync({count: 10})
this.decr({count: 10})
},
// 将 this.increment() 映射为 this.$store.dispatch(‘increment‘)
// 将 this.decrementAsync() 映射为 this.$store.dispatch(‘decrementAsync‘)
...mapActions([‘increment‘, ‘decrementAsync‘]),
// 对象提交方式
// 将 this.incr() 映射为 this.$store.dispatch(‘increment‘)
// 将 this.decr() 映射为 this.$store.dispatch(‘decrementAsync‘)
...mapActions({incr: ‘increment‘, decr: ‘decrementAsync‘})
}
}
原文:https://www.cnblogs.com/JunLan/p/12721048.html