一、vuex概述
先回顾一下学习vuex之间的组件之间的通讯
父组件给子组件传值 props,v-bind
子组件传递负组件传值 v-on接收自定义事件,$emit发送自定义事件
这种组件通信方式太有局限性了,只适合在小范围内传递参数,如果需要频繁的大范围的实现数据共享,这种组件通信方式有点力不从心了…
1.2 Vuex是什么
Vuex
是实现组件全局状态/数据管理的一种方案,可以方便实现组件之间的数据共享。
1.3 使用vuex储存数据的好处
- 能够在vuex中集中管理共享的数据,易于开发和后期维护。
- 能够高效地实现组件之间的数据共享,提高开发效率。
- 储存在vuex中的数据都是响应式的,可以实时保持数据与页面的同步。
1.4 什么样的数据适合储存到vuex中?
一般情况下,只有组件之间共享的数据
,才有必要储存到vuex中,对于组件私有的数据,依旧储存在组件自身的data
中即可。
二、安装vuex
yarn add vuex
三、配置vuex
- 创建一个独立的
store.js
文件初始化vuex。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
- 创建一个store实例,并把它暴露出去。
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
modules: {}
})
- 在入口文件引入
store.js
,并把它挂在到vue实例
// 引入暴露出来的store文件
import store from 'store.js'
new Vue({
store,
render: h => h(App),
}).$mount('#app')
四、vuex的核心概念
4.1 state
-
state是用于存放并共享数据,所有的组件都可以使用
this.$store.state.数据名称
来访问全局数据。因为store被挂载到了vue实例当中,所以组件可以使用
this
访问state
。 -
第二种访问
state
的方式:使用mapState
函数访问。
通过导入mapState
函数,将当前组件需要的全局数据
,映射为当前组件的computed
计算属性。
// 1. 在当前组件引入 mapState 函数
import { mapState } from 'vuex'
// 2. 将state中的全局数据映射为当前组件的计算属性
computed: {
...mapState(['message'])
}
mapState
以数组的方式存放数据,每个数组元素就是state
中的全局数据。
在实际开发中,两种访问state的方式你都可以使用。使用mapState
,在组件内,不需要再使用$store.state
拿数据了,可以直接使用this
。
注意:千万不要通过$store.state
修改state
中的数据全局数据!虽然可以,但是不推荐!
4.2 Mutations
上面说到,不要通过$store.state
去修改全局数据。所以我们可以使用mutations
函数来修改,官方说到,所有的同步操作
都可以交给mutations
来做。
先在mutations
中定义一个函数,然后在当前组件,调用commit
函数,调用此函数的同时,便会触发mutations
定义的那个函数。
触发 Mutations
// 1. 在 mutations 定义一个修改 state 数据的函数
mutations: {
add(state) {
state.counter++
}
}
// 2. 在组件内调用触发这个函数
methods: {
addition() {
this.$store.commit('add')
}
}
mutations
定义的函数的第一个参数,永远都是state
,修改就通过state.数据
修改,而不是使用this
。
commit
的第一个参数是mutations
中定义的那个函数的名称。它的作用就是调用某一个mutations
定义的函数。
Mutations 传递参数
在组件调用commit
函数的同时,还可以传递参数,且mutations
定义的那个函数可以接收。
// 1. 调用函数时,传递参数
methods: {
addition() {
this.$store.commit('add', 10)
}
}
// 2. 接收参数,让 state 的 counter +10
mutations: {
add(state, num) {
state.counter += num
}
}
触发 Mutations 的第二种方式
上面讲了,state
可以通过mapState
函数访问全局数据。mutations
也有一个mapMutations
函数,将需要的mutations
函数,映射为当前组件的methods
方法。
注意了:mapState
是映射为当前组件的计算属性,而mapMutations
是映射为当前组件的methods
方法。
// 1. 引入 mapMutations 函数
import { mapMutations } from "vuex";
// 2. 使用this.add调用函数,调用此函数时,也可以传递参数,我传递了 10
methods: {
...mapMutations(['add']),
addition() {
this.add(10)
},
}
其实你可以这样认为,使用mapMutations
,就相当于把mutations
定义的函数变成了组件自己的函数。
4.3 Actions
在这之前,如果想要实现一个需求,当一个按钮点击,1秒之后,我们让state
的counter
加10,使用mutations
做的话,其实也可以,但是会有问题!
如图所示,页面中确实是实现了效果,但是问题是,state
中counter
为什么为什么还是0呢?
这个官方给出了解释:mutations
不能实现异步操作
。像上面这个需求,就是一个异步操作!不要在mutations
中写异步代码!
有缺必有补,vuex提供了actions
函数,它可以用于处理异步任务。
如果通过异步操作变更数据,必须经过actions
,不可以直接使用mutations
,但是还是要通过触发mutations
得方式简介变更数据!
-
执行过程是这样的:
VueComponents -> Actions -> Mutations -> State
-
如果没有异步任务,那么执行过程是这样的:
VueComponents -> Mutations -> State
没有异步任务,可以不经过actions
,比如:有的人一出生就是百万富翁,以后直接继承家产,而有的人,就只能靠自己的努力(我就是后者 ~)。
如果你觉得我说的比较抽象,那么你可以看官方的一张图:
触发 Actions
- 在当前组件调用
dispath
函数来触发actions
定义的addASync
异步任务,并传递一个参数
addition() {
this.$store.dispatch('addAsync', 10)
}
- 在
actions
中,使用context
,触发mutations
定义的同步任务。
// mutations 写同步任务的代码
mutations: {
add(state, step) {
state.counter += step
},
}
// actions 写异步任务的代码
actions: {
addAsync(context, step) {
setTimeout(() => {
context.commit('add', step)
},1000)
}
}
commit
用于触发某个moutations
dispatch
用于触发某个actions
触发 Actions 的第二种方式
Actions
也有一个mapActions
,使用方式和上面的一致。
- 引入
maoActions
- 将
Actions
定义的函数映射为当前组件的methods
方法。
要记住,使用这种方式触发它们,就相当于在该组件内定义了这些个函数。可以直接this
使用。
在template
中调用函数,可以省去自己定义函数这部操作,直接@click="映射过来的函数"
,但前提是你要使用mapMutations
,mapActions
这些函数触发它们。
4.4 Getters
-
Getters
用于对Store
中的数据进行加工处理成新的数据。 -
比如说:
state
中有一个数组,里面存放的是若干个个人信息对象,要对这组对象进行筛选,把小于18岁的人筛选出来,返回一组新的数据,类似于Vue
的计算属性。 -
它不会改变
Store
中的数据!Store
中的数据发生改变,Getters
也会发生改变。相当于对数据进行包装处理。
-
在组件内通过
this.$store.getters.函数名
拿到处理后的数据。记得写return
筛选小于18岁的人
getters: {
screenAge(state) {
return state.profile.filter(item => item.age < 18)
}
}
- 在组件内拿到筛选后的数据。
<h2>{{$store.getters.screenAge}}</h2>
当然你也还可以使用mapGetters
拿到数据。把Getters
定义的函数映射到当前组件的计算属性
里面。
<h2>{{screenAge}}</h2>