在理解Vuex的使用和原理以前首先要知道Vuex是什么?按照官方的说法,Vuex是专门为Vuejs应用程序设计的一款状态管理模式,相似于React中的Redux。它采用集中式存储管理应用的全部组件的状态。前端
下面图片很清晰的展现出了Vuex的组成结构vue
state 是 Vuex 的数据中心,也就是说state是用来存储数据的。vuex
getters 和 组件的 computed 相似,方便直接生成一些能够直接用的数据。当组装的数据要在多个页面使用时,就可使用 getters 来作。npm
mutations提交更改数据,使用store.commit方法更改state存储的状态。数组
Action 提交的是 mutation,而不是直接变动状态。Action 能够包含任意异步操做。缓存
npm install vuex --save
复制代码
方式二: yarn 方式yarn add vuex
复制代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
复制代码
方式一: this.$store.state获取bash
经过在根实例中注册 store 选项,该 store 实例会注入到根组件下的全部子组件中,且子组件能经过 this.$store 访问到异步
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
复制代码
方式二: mapState 辅助函数获取(推荐)函数
当一个组件须要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,咱们可使用 mapState 辅助函数帮助咱们生成计算属性,让你少按几回键:ui
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
}
})
}
复制代码
当映射的计算属性的名称与 state 的子节点名称相同时,咱们也能够给 mapState 传一个字符串数组。
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
复制代码
有时候咱们须要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
复制代码
若是有多个组件须要用到此属性,咱们要么复制这个函数,或者抽取到一个共享函数而后在多处导入它——不管哪一种方式都不是很理想。
Vuex 容许咱们在 store 中定义“getter”(能够认为是 store 的计算属性)。就像计算属性同样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。
方式一: 经过属性访问
store.getters.doneTodos
复制代码
方式二: 经过方法访问
你也能够经过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时很是有用。
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
复制代码
store.getters.getTodoById(2)
复制代码
注意,getter 在经过方法访问时,每次都会去进行调用,而不会缓存结果。
方式三: mapGetters 辅助函数获取(推荐)
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
复制代码
若是你想将一个 getter 属性另取一个名字,使用对象形式:
mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
复制代码
上面咱们说了更改 Vuex 的 store 中的状态的惟一方法是提交 mutation,Vuex 中的 mutation 很是相似于事件:每一个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数。
使用常量替代 Mutation 事件类型
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
复制代码
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 咱们可使用 ES2015 风格的计算属性命名功能来使用一个常量做为函数名
[SOME_MUTATION] (state) {
// mutate state
}
}
})
复制代码
固然使用常量代替Mutation事件类型也不是必须的,若是你不喜欢,你彻底能够不这样作。
在组件中提交 Mutation
你能够在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(须要在根节点注入 store)。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
复制代码
Action的注册
Action 函数接受一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用 context.commit 提交一个 mutation,或者经过 context.state 和 context.getters 来获取 state 和 getters。当咱们在以后介绍到 Modules 时,你就知道 context 对象为何不是 store 实例自己了。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
复制代码
分发 Action
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
复制代码
在组件中分发 Action
你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(须要先在根节点注入 store)
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')`
})
}
}
复制代码
至此Vuex的使用及原理就介绍到这里,若是还有不一样理解的小伙伴们还请下发留言。若是有写的很差的地方还请多多指教。我会继续更新有关前端的技术文章的。