这篇文章主要介绍了vuex中五大属性和使用说明(包括辅助函数),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。
1.state
vuex的基本数据,用来存储变量
// state存储基本数据
state: {
userId: '',
}
在Vue中使用 this.$store.state.userId
我们可以通过Vue的computed获得Vuex的state
// An highlighted block
const store = new Vuex.Store({
state: {
count:0
}
})
const app = new Vue({
//..
store,
computed: {
count: function(){
return this.$store.state.count
}
},
//..
})
mapState辅助函数
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。
为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键。
将 Vuex store 中的状态映射为组件的计算属性, mapState
有两种常用的写法,分别是对象语法和数组语法:
数组语法
import { mapState } from 'vuex';
export default {
// 映射计算属性
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
//...
}
在数组语法中,我们只需列出需要映射的状态属性名称,而不需要指定映射的模块。这种写法会自动将这些属性映射到组件的根状态(即this.$store.state
)中。
对象语法
写法一
import { mapState } from 'vuex';
export default {
// 映射计算属性
computed: mapState({
// 映射 this.count 为 store.state.count
count:state=>state.uploadfile.count
})
//...
}
在对象语法中,我们通过一个对象来定义映射关系,在键值对中指定组件中的计算属性名称作为键,然后使用箭头函数返回需要映射的状态值。
写法二
import { mapState } from 'vuex';
export default {
computed: {
...mapState('uploadfile', ['count'])
},
// ...
};
推荐使用第二种这种写法。原因如下:
① 语法更加简洁明了,直接指定模块名和需要映射的属性名称,不需要额外的箭头函数或命名空间参数。
② 在组件中使用count时,可以清晰地知道该属性来自于哪个模块,提高了可读性。
③ 当需要映射多个属性时,可以在数组中列出所有需要映射的属性,使代码更加整洁。
总结:
在大型项目中,更推荐使用对象语法 ...mapState('module', ['property']) 来映射状态属性。这是因为大型项目通常具有复杂的模块化结构,并且存在多个模块之间的状态共享和交互。
以下是选择对象语法的原因:
① 模块明确:在大型项目中,往往存在多个模块,每个模块都有自己的状态属性。使用对象语法可以明确指定所需属性属于哪个模块,将状态属性与特定模块关联起来,提高了代码的可读性和可维护性。
② 避免命名冲突:在大型项目中,可能会存在多个模块中同名的状态属性。使用对象语法,可以避免不同模块中的状态属性名称冲突,减少潜在的错误。
③ 模块解耦:使用对象语法可以将组件与特定模块解耦。当模块内部的状态结构发生变化时,只需更新模块内部的代码,而不需要修改组件中的映射代码。这有助于降低代码的耦合性和维护成本。
总之,对于大型项目来说,对象语法更具可扩展性、可读性和维护性,能更好地管理和组织模块化状态属性。使用对象语法能够更清晰地表达状态属性来自于哪个模块,并避免潜在的冲突和错误。
state:用来存储公共状态, state中存储的数据都是响应式的。
响应式原因:state里面有getters、setters方法;data中的数据也是响应式的,因为里面也有getters和setters方法。
在computed属性中来接收state中的数据,接收方式有2种(数组和对象,推荐对象)
优点:
① 本身key
值是别名,要的是val
值,key
的值a 和 val="a"一样就行,随意写。减少state
里面长的属性名。
② 可以在函数内部查看state
中的数据,数组方式的话,必须按照state
中的属性名。
2.getters
从基本数据(state)派生的数据,相当于state的计算属性,具有返回值的方法。
// getter
getters: {
userIdDouble: function(state){
return state.userId * 2
}
在vue中使用 this.$store.getters.userIdDouble
与state一样,我们也可以通过Vue的computed获得Vuex的getters。
getters接收state作为其第一个参数,接受其他 getters 作为第二个参数,如不需要,第二个参数可以省略如下例子:
const store = new Vuex.Store({
state: {
count:0
},
getters: {
// 单个参数
userIdDouble: function(state){
return state.count * 2
},
// 两个参数
userIdDoubleAndDouble: function(state, getters) {
return getters.userIdDouble * 2
}
}
})
const app = new Vue({
//..
store,
computed: {
userIdDouble: function(state){
return this.$store.getters.userIdDouble
},
userIdDoubleAndDouble: function(state,getters){
return this.$store.getters.userIdDouble
},
},
//..
})
getters
类似于组件里面computed
,同时也监听属性的变化,当state
中的属性发生改变的时候就会触发getters
里面的方法。getters
里面的每一个方法中都会有一个参数 state
。
mapGetters 辅助函数
与state一样,我们也可以通过Vue的Computed获得Vuex的getters
对象写法
写法一
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({
userIdDouble:'userIdDouble',
// 等价于
//userIdDouble: function(){
// return getters.uploadfile.userIdDouble
//},
userIdDoubleAndDouble:'userIdDoubleAndDouble'
// 等价于
//userIdDoubleAndDouble: function(){
// return getters.uploadfile.userIdDoubleAndDouble
//}
})
},
//..
}
写法二
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters('uploadfile',['userIdDouble','userIdAndDouble')
},
//..
}
数组写法
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters(['userIdDouble','userIdAndDouble')
},
//..
}
3. mutations
提交更新数据的方法,必须是同步的(如果需要异步使用action)。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。提交mutation是更改Vuex中的store中的状态的唯一方法。
mutation必须是同步的,如果要异步需要使用action。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。
// mutations
mutations: {
SET_USER: (state, userId) => {
state.userId = userId
},
},
commit:同步操作,写法: this. s t o r e . c o m m i t ( 'mutations方法名,值 ) this. store.commit('mutations方法名',值) this. store.commit(‘mutations方法名’,值)this.store.commit(‘SET_USER’,‘123456’)
使用mapMutations–代替 $store.commit()- 传参的时候直接在行内写参数就可以了-
mapMutations 辅助函数
与其他辅助函数类似,你可以在组件中使用 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({
add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
})
}
}
4. actions
和mutation的功能大致相同,不同之处在于 ==》
1. Action 提交的是 mutation,而不是直接变更状态。
2. Action 可以包含任意异步操作。Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
// actions
actions: { // {} 是es6中解构,把对象解构成属性
login({ commit }, value) {
commit('SET_USER', value)
// commit('SET_TOKEN', value2)
},
}
dispatch:异步操作,写法:
this.$store.dispatch(‘mutations方法名',值)
actions
里面的函数主要用来处理异步操作以及一些业务逻辑,每一个函数里面都有一个形参,这个形参是一个对象,里面有一个commit
方法,这个方法用来触发mutations
里面的方法。
mapActions辅助函数
你在组件中使用 this.$store.dispatch(‘xxx’) 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):
// An highlighted block
import { mapActions } from 'vuex'
export default {
//..
methods: {
...mapActions([
'incrementN' //映射 this.incrementN() 为 this.$store.dispatch('incrementN')
]),
...mapActions({
add: 'incrementN' //映射 this.add() 为 this.$store.dispatch('incrementN')
})
}
}
mutations
里面的函数主要用来修改state
中的数据。mutations
里面的所有方法都会有2个参数,一个是store
中的state
,另外一个是需要传递的参数。
理解state
、actions
、mutations
,可以参考MVC
框架。
state
看成一个数据库,只是它是响应式的,刷新页面数据就会改变;actions
看成controller层,做数据的业务逻辑;mutations
看成model层,做数据的增删改查操作。
至此,可以简单总结一下辅助函数通过vuex的使用,比喻成映射关系为:
mapState/mapGettes--->computed
;mapAcions/mapMutations---->methods
5. modules
使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。
为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:
例如:分模块形式管理数据,比如user模块管理用户信息数据,cart模块管理购物车数据,shop模块管理商品信息数据。
import vue from 'vue'
import Vuex from 'vuex'
Vue.use(vuex);
const state= ()=>{ token:''}
const actions = {
set_token({commit},val){
commit("to_token",val)
}
}
const mutations = {
to_token(state,val){
state.token=val;
}
}
const getters = {}
//user模块
let user = {
namespaced: true, //一定要开始命名空间。
state: { userid: 1234 },
actions: {
},
mutations: {
SET_USERID(state, val) {
state.userid = val;
}
},
getters: {
}
}
//购物车数据的模块
let cart = {
namespaced: true,
state: { userid: 567 },
actions: {
},
mutations: {
},
getters: {
}
}
const store = new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
user,
cart
},
plugins: [createPersistedState({
storage: sessionStorage,
key: "token"
})]//会自动保存创建的状态。刷新还在
})
export default store
home.vue如何使用:获取user模块的`userid`
this.$store.state.user.userid
// 前面是指定模块user 中的SET_USERID 方法,后面是传参 可以是对象、数组、字符串等
this.$store.commit("user/SET_USERID",12345)
模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
简单来说就是可以把以上的 state、mutation、action、getters 整合成一个user.js,然后放到store.js里面。
小结:modules属性:模块,把公共的状态按照模块进行划分。
1、每个模块都相当于一个小型的Vuex ;
2、每个模块里面都会有state getters actions mutations ;
3、切记在导出模块的时候加一个 namespaced:true 主要的作用是将每个模块都有独立命名空间;
4、多人协作开发的时候,可能子模块和主模块中的函数名字会相同,这样在调用函数的时候,相同名字的函数都会被调用,就会发生问题。为了解决这个问题,导出模块的时候要加namespace:true
番外:vuex的五大属性关系一览
6.命名空间
模块开启命名空间后,享有独自的命名空间。示例代码如下:
export default {
namespaced: true,
....
}
mapState
、mapGetters
、mapMutations
、mapActions
第一个参数是字符串(命名空间名称),第二个参数是数组(不需要重命名)/ 对象(需要重命名)。
mapXXXs('命名空间名称',['属性名1','属性名2'])
mapXXXs('命名空间名称',{
'组件中的新名称1':'Vuex中的原名称1',
'组件中的新名称2':'Vuex中的原名称2',
})
7.Vuex使用方法
使用方法:
① 安装Vuex:npm install vuex --save
② 在main.js中,导入Vuex,并使用Vue.use()方法注册Vuex。
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
new Vue({
store,
render: h => h(App)
}).$mount('#app')
③ 在组件中使用vuex中的数据和方法。
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
increment() {
this.$store.commit('increment')
}
}
}
</script>
④ vuex综合案例
下面是一个简单的Vuex使用方法的示例:
// 引入Vue和Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建一个Store
const store = new Vuex.Store({
// 定义State
state: {
count: 0
},
// 定义Mutation
mutations: {
increment: state => state.count++,
decrement: state => state.count--
},
// 定义Getter
getters: {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
},
// 定义Action
actions: {
incrementIfOdd ({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit('increment')
}
}
}
})
new Vue({
el: '#app',
store,
template: `
<div>
<p>Count: {{ count }}</p>
<p>Even or Odd? {{ evenOrOdd }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
<button @click="incrementIfOdd">IncrementIfOdd</button>
</div>
`,
computed: {
count () {
return this.$store.state.count
},
evenOrOdd () {
return this.$store.getters.evenOrOdd
}
},
methods: {
increment () {
this.$store.commit('increment')
},
decrement () {
this.$store.commit('decrement')
},
incrementIfOdd () {
this.$store.dispatch('incrementIfOdd')
}
}
})
这个代码创建了一个Vuex Store,并定义了State、Mutation、Getter、Action。然后将Store实例与Vue实例关联。在Vue组件中,使用计算属性(computed)和方法(methods)来访问State、Getter和Action。在方法中,使用commit来提交Mutation,使用dispatch来分发Action。
参考资料
—— Vue | Vuex模块化及命名空间namespaced的使用_儒雅烤地瓜的CSDN博客 ——
几分钟弄懂Vuex五大属性和使用方式_脚本之家 | Vuex中5个属性使用方法举例讲解_脚本之家