Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
这是官网给出的解释,看起来很绕。其实通俗的来讲,Vuex就是跟我们的vue项目提供了一个仓库用来存储所有组件的状态/数据等等,仓库只有一个入口和出口,并且有人看管,出入还需要登记记录,这样我们只要看记录就知道谁取了数据,对数据做了什么事。这样我们就把组件共享的状态都抽离了出来,交给Vuex实例来管理,方便我们管理一个大型项目。所以,Vuex主要是用来解决以下问题:
- 管理项目所有组件的状态
- 多个视图依赖于同一状态
- 来自不同视图的行为需要变更同一状态
通过这样一番操作,我们的组件树就变成了一个单一且庞大的视图,不管在视图树的哪个细枝末节,任何组件都能获取到他的状态和触发行为。并且,通过预设定规则,我们可以强制组件状态间保持独立,代码也就变得更加结构化且易于维护。
安装
npm install vuex --save
使用
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) //类似koa,通过这种中间件的方式,使用Vuex
const store = new Vuex.Store({ //实例化一个唯一的Vuex.Store实例
state: { //用来存放所有组件依赖的、我们需要统一管理的状态
count: 0
},
mutations: { //用来存放所有组件中需要用到的、我们需要统一管理的、用来改变状态的行为
increment (state) {
state.count++
}
}
})
通过这种方式,我们创建了一个最简单的Vuex仓库的实例(一个项目中只能有唯一的Store实例),通过这种单一状态树,我们才能做到强制的管理所有组件的状态。
state
上面我们已经实例化了一个状态仓库store
,其中的store.state
就是用来存放所有状态的单一状态树,那么我们要如何在组件中获取到需要的状态呢。最简单的办法就是用计算属性computed
来获取。
通过计算属性获取
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
通过计算属性中的store.state.count
我们就拿到了需要的count数据,如果数据发生了变化,也会自动计算count的计算属性值。但是这样,会让每个组件都依赖全局变量store
。所以,Vue提供了一种将store注入到所有子组件当中的方式:
const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
// store:store,
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
这样,就把store对象注入到了所有子组件内部,这样子组件就可以通过this.$store
访问到。
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
通过以上两种利用计算属性直接监听store.state
的方式,就轻松的取到了我们需要的状态信息。但是试想一下,这是只有一个状态,用计算属性写起来还算清晰,但是如果我们组件里面有20个状态需要获取,难道我们要写20个computed的方法吗?显然,虽然可以这么干,但是太不优雅和美观了。
所以,vuex给我们提供了一种函数方法,优雅的解决这个问题——mapState
辅助函数。
通过mapState辅助函数获取
mapState
辅助函数返回的是一个对象,通过对象运算展开符...
,我们就可以吧这个对象传递给该组件,与本地局部状态一起使用。
computed: {
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
'count','...','...'
})
}
Getters
先回想以下使用computed
计算属性的最初原因是什么——是我们需要对响应式数据进行一些派生的处理,比如,count++
,列表循环等等。我们把这些处理派生逻辑行为的方法都放到了computed
里面,进行集中管理。同理,vuex也给我们提供了一种集中管理state派生状态的方法:Getters
。
它和计算熟悉一样:
- 会缓存
- 会响应数据状态的变化
- 集中管理所以派生方法
初始化
在初始化store
对象的时候,Getters
接收state
作为第一个参数传入,以下是使用方法:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
// 初始化getters
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
...:...,
}
})
getter
通用暴露给了外部一个store.getters
的对象进行访问。
通过属性访问
通过属性可以直接获取到我们需要的值store.getters.doneTodes
,因此我们就可以在子组件中方便的获取到:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodos
// return store.getter.doneTodos
}
}
通过方法访问
我们可以让getters
返回一个回调函数,实现给getters
的传参,这一般在查询数组是非常好使。
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
通过mapGetters辅助函数获取
同样,Vuex也给我们提供了一个回调函数,优雅的获取getters。
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
mutation
mutation
给我们提供了唯一一个变更state状态的方法,通过这个我们就可以监控到所有组件变更state
的行为。
mutation
类似于事件监听,每个matation
提供了一个字符串的事件类型(Type)和一个回调函数(Handle)。回调函数是用来改变state状态的地方,并且state将会作为函数的第一个参数传入:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
调用mutation
我们调用mutation
的时候,不能使用对象进行操作:store.mutations.increament
,因为Vuex给我们规定了一个唯一的提交更新的入口: store.commit('increament')
。
提交payload
每个mutation
的第二个参数是payload
,也就是传入的参数:
mutations: {
increment (state, n) {
state.count += n
}
}
这样在外部调用的时候,可以通过payload传入参数:store.commit('increament',10)
,这样就实现了参数的传入。
需要注意的一点是:mutation
是一个同步函数,如果需要在处理过程中调用异步方法,那么就需要用到下面讲的:action
action
action
与mutation
声明和调用的方式都很类似,唯一不同的是:
action
内部是支持调用异步方法的。action
提交的是mutation
,而不是直接更改state
声明action
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
同样的,action
也支持设置payload
来传入参数,这里就不展开来了。
调用action
同样的action
提供了dispatch
发的方式进行调用:store.dispatch('increment')
。或者,可以使用action
提供的辅助函数mapActions
进行调用:
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的基本用法,主要包括:如何初始化、state、getter、mutation、action的用法。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!