只讲操作,不谈原理,适合工作用,不适合面试
一个最基本的vuex可以由一个js文件来实现,也是我们使用脚手架初始化vue项目默认生成的模式,一个最基本的vuex包括state、mutations、actions,其中actions可以用来写异步代码,而mutations只能写同步代码,所以在一些更简单的项目中,actions都可以不用用到。但一个vuex的完整模块包括:state、mutations、actions、getters、modules,其中getters可以看作在vuex中的计算属性,modules就是一些子模块,在一些大型项目中对业务进行拆分。
下面我从最简单的模式到使用模块,再到使用vuex的map语法糖对vuex的操作进行演示一遍:
不使用模块的基础模式
先看看vuex相关的文件夹,放在src下的store文件夹,里面有一个index.js文件,为vuex的入口,如果不使用模块,可以将所有相关代码写在index.js文件里面,下面是最基础的index.js文件演示:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
mainname: 'main'
},
getters: {
getMainname: (state) => {
return state.mainname
}
},
mutations: {
setMainname: (state, data) => {
state.mainname = data
}
},
actions: {
asyncSetMainname: ({ commit }, data) => {
commit('setMainname', data)
}
}
})
可以看到除了modules,其他属性都使用到了。其中mutations的方法就是直接修改state里面的变量,而actions是通过提交mutations去修改state,而不能直接修改state,actions中的方法的第一个参数是一个context上下文对象,可以通过context.commit提交mutations,上面的代码我将它解构。
下面是在组件中的操作:
获取state:
this.$store.state.mainname // main
提交mutations:
this.$store.commit('setMainname', 'main111') // 参数为mutations方法名,数据
提交actions:
this.$store.dispatch('asyncSetMainname', 'main') // 参数为actions方法名,数据
获取getters:
this.$store.getters.getMainname // main
一般写在计算属性中:
computed:{
mainname() {
return this.$store.getters.getMainname
}
}
这就是最基础的vuex用法。
使用模块
如果要将vuex拆分成几个模块,一般在index.js同级下新建一个modules文件夹,假如我现在拆分出一个叫user的模块,目录结构就变成:
vuex的子模块同样包含state、mutations、actions、getters这些属性,下面是user.js的代码:
const state = {
username: 'user'
}
const getters = {
getUsername: (state) => {
return state.username
}
}
const mutations = {
setUsername: (state, data) => {
state.username = data
}
}
const actions = {
asyncSetUsername: ({ state, commit }, data) => {
commit('setUsername', data)
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
}
主体内容与入口文件index.js基本一致,最后将所有属性导出,同时要导出一个namespaced为true,为开启命名空间,以免混乱,然后在index.js中将这个模块引入,下面是改动后的index.js:
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
mainname: 'main'
},
getters: {
getMainname: (state) => {
return state.mainname
}
},
mutations: {
setMainname: (state, data) => {
state.mainname = data
}
},
actions: {
asyncSetMainname: ({ state, commit }, data) => {
commit('setMainname', data)
}
},
modules: {
user
}
})
现在实际上我的vuex是有两个模块,一个index主模块,一个user模块,那在组件中如何操作呢:
获取state:
如果和上面的写法一样的话,获取的是index主模块中的state变量
如果想要获取user模块中的state,需要在后面加上模块名称
// 默认
this.$store.state.mainname // main
// 获取子模块
this.$store.state.user.username // user
提交mutations:
和获取state的逻辑一样,不加模块名称提交的是index中的mutations,要提交子模块中的mutations就得加上模块名
this.$store.commit('user/setUsername', 'user111') // 有点像url写法,在方法名称前加上模块名
如果不加模块名,会去index.js中找这个mutations方法,找不到就会报错
this.$store.commit('setUsername', 'user111') // 报错
提交actions,逻辑一样:
this.$store.dispatch('user/asyncSetUsername', 'user111')
获取getters:
computed:{
mainname() {
return this.$store.getters['user/getUsername']
}
}
到这里vuex的基本操作就都说完了,包括不带模块的,带模块的,下面是使用vuex自带的map语法糖对操作进行简化。
使用vuex的map语法糖对操作进行简化
我们在组件中操作vuex,都得通过this.$store点点点,看起来比较繁琐,vuex提供了vuex和组件方法进行映射的语法糖,下面我演示一下这些map语法糖的写法:
在组件中,先从vuex中引入几个方法:
import { mapMutations, mapActions, mapGetters } from 'vuex'
从名字就可以看出就是和mutations、actions、getters在组件中做映射,下面先看不使用模块的情况,先从
mapMutations开始演示:
mapMutations是一个方法,返回一个对象,对象里面就是vuex里面的mutations方法,所以在和组件做映射时,要写在methods中,然后把这个对象解构:
methods: {
// mapMutations可以接收一个数组为参数,数组项就是vuex里面mutations方法的名称
...mapMutations([
'setMainname'
]),
然后在别的方法中执行:
fn() {
this.setMainname('mainname1111')
}
}
上面的写法就相当于:
methods: {
fn() {
this.$store.commit('setMainname', 'main1111')
}
}
不仅可以映射到组件中的方法,还可以在组件中修改mutations方法的名称:
methods: {
// 将mapMutations的参数从数组改成对象,key值为自定义的方法名,value中为原来mutations方法的名称
...mapMutations({
setMainnamePro: 'setMainname'
}),
fn() {
this.setMainnamePro('main1111')
}
}
mapActions和mapMutations用法一模一样,不改变actions方法名称时参数传数组,改变actions方法名称时参数传对象:
methods: {
...mapActions({
asyncSetMainnamePro: 'asyncSetMainname'
}),
fn() {
this.asyncSetMainnamePro('main111')
}
}
相当于:
methods: {
fn() {
this.$store.dispatch('asyncSetMainname', 'main111')
}
}
mapGetters道理也是一样,只不过是写在computed中:
computed: {
...mapGetters([
'getMainname'
])
}
在别的地方用的话跟使用普通计算属性一样,注意后面没有括号:
this.getMainname
同样可以修改名称,同样是参数把数组改成对象:
computed: {
...mapGetters({
mainname: 'getMainname'
})
}
在别的地方:
this.mainname
几个map的基本用法就说完了,上面说的是不用模块的,也就是拿的都是index.js里面的属性,那如果要拿user模块里面的属性呢,其实也非常简单,只需要在几个map方法的第一个参数写上模块名称就可以,其他用法一模一样:
...mapMutations('user', [
'setUsername'
])
...mapActions('user', [
'asyncSetUsername'
])
...mapGetters('user', [
'getUsername'
])
同样把第二个参数写成对象就可以自定义vuex里面方法的名称,用法与上面一样。
这就是本次超人鸭分享的vuex一些操作写法,主要是当用到模块与map语法糖时,在组件中如何操作。欢迎大家指教哦。