vuex
vuex是状态管理模式。
需求:比如在我们的博客中,每个组件中都需要用户的登录状态以及登录信息(多个视图依赖于同一状态,来自多个视图的行为需要变更同一状态),这个时候,就可以使用vuex来维护这个状态。
vuex的核心就是仓库store,其实就是一个容器,包含应用中的很多状态(state),以及管理状态的方法。vuex的状态存储是响应式的。
const store = new Vuex.Store({
state: {
isLogin: false
},
getters:{},
mutations:{},
actions:{}
})
下面介绍核心概念
一、State
state翻译为状态,就是需要维护的状态,在上边例子已经展示。
问题:如何获得vuex状态?
我们上边已经说了,vuex的状态存储是响应式的。
vue文档中,data中,有这么一句话:大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。
那么,如何获取呢?我们么可以通过计算属性返回某个状态。
计算属性,是用来处理逻辑运算的
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.isLogin
}
}
}
那么,如果我们有很多组件,这样,太烦了!
vuex提供了store选项,将状态从根组件注入到每个子组件中。然后我们在子组件中,就可以通过this.$store
访问。(如何访问,当然还是通过computed属性访问)
const app = new Vue({
el: '#app',
store
})
感觉这俩没啥区别?
区别挺大的:要是我们的组件比较多,注入之后,就不要在组件中一个一个导入了。
辅助函数mapState
用处:当一个组件需要获取多个状态的时候,如果我们将每一个都声明为计算属性,真的会很烦,辅助函数可以帮我们简化这个过程。
比如,在我们的博客中,要维护的状态有用户的登录状态以及用户的登录信息:
const store = new Vuex.Store({
state: {
isLogin: false,
user: {}
}
})
辅助函数的用法:
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
//当映射的计算属性名称和state中状态名称相同时,这么用
//就是this.isLogin = store.state.isLogin
computed: mapState([
'isLogin',
'user'
])
//简化上边的写法,使用对象展开符
computed: {
...mapState({
'isLogin','user'
})
}
二、Getter
getter就像store的计算属性一样。
比如我们在state维护了一个数组,我们将state的数据做一些处理,再使用。按照我们刚才说的,当任何一个组件需要使用处理后的数据时,都需要把这个过程再重复一次,显然是不划算的。
如果我们能在store中将数据处理好,再暴露出来,岂不是更好。
这就是getter的用途。
在我们的博客项目中,为什么也使用getter呢?
我们的状态很简单,只有isLogin/user,用来存储用户的登录状态以及信息。但是麻烦的是,我们分了模块。
store
---modules
------auth.js
------blog.js
---index.js
这样依赖,每次实际上都是看到的状态state->auth->isLogin/user,这样的结构麻烦,不方便访问,所以才将其放到getter中,getter和state是同级的。直接用就可以
const getters = { isLogin: state=>state.isLogin, user: state=>state.user }
就像上边的例子一样,Getter接受state作为其第一个参数。
问题:如何访问getter
- 通过属性访问
- 通过方法访问
mapGetters辅助函数:用法和刚才的都一样
三、Mutation
其实,这个问题应该在最开始就提:
state我们用来定义状态。要是我想要改这些状态呢?
比如,用户需要注销登录、页面跳转到另一个人的时候,我们需要将用户信息更改掉。这些需求,我们就需要通过mutation来完成。
Mutation是干啥的?
文档中说:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
mutation示例:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
如果想调用mutation,就需要用:
store.commit('increment')
问题:如果我们在修改状态的时候,需要传入数据呢。
这就是payload(载荷)。其实就是向store.commit
传入额外的参数就行了。
store.commit('increment', payload)
Mutation必须是同步函数
在组件中当然也是可以提交mutation的
this.$store.commit('xxx')
或者使用辅助函数也是可以
我没用,需要时,再看文档把
四、Action
既然mutation必须是同步的,那么我们就用action处理异步就可以了。
需要注意:
- Action提交的是mutation,不可直接变更状态
我们的博客项目中,我们要维护用户的登录状态以及信息。
用户登录前后的信息,我们肯定是需要维护的,但是登录、注册之类的要搞成异步啊。那么这些就只能在Action中定义了,当在Action中异步登录成功,就可以开开心心提交mutation修改登录状态了。
Action的用法:(博客登录异步处理,当然auth.login肯定封装好的)
const actions = {
login({ commit }, { username, password }) {
return auth.login({ username, password })
.then(
res => {
commit('setUser', { user: res.data })
commit('setLogin', { isLogin: true })
})
}
}
或者看文档的例子,可能更直接一点。
问题:既然Action都是异步的,那啥时候结束呢?(结束之后,才好去提交mutation啊)
使用promise就行了...上边例子,auth.login
就是返回的promise对象,接着then就行了...
async/await当然也可以...就是我没太用过
问题:搞了这么久,Action如何在组件中使用啊?
使用mapActions在组件的method中映射下,直接this.xxx
用就行了
网友评论