1. 介绍
Vuex是Vue官方推出的一个状态管理工具,其能生成一个单独的全局状态实例,其有以下特点:
- 能够在vuex中集中管理共享的数据,利于开发和后期的维护
- 能够在Vue的各个组件中实现访问和共享,能够有效解决以下兄弟组件、祖孙组件等跨代组件的通信困难问题。
- 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步。
2. 安装
//CDN
https://unpkg.com/vuex@3.6.2
//NPM
npm i vuex@ 3.6.2 -s
注意事项:版本号在3.6.2以下的vuex适用于vue2,若在vue2的工程项目中直接npm i vuex -s
会报如下的错误
解决办法是指定版本号,vue2使用的版本目前最高支持到3.6.2,具体可在更新记录中进行查阅。
3.核心概念
3.1 State
State相对于vuex来说就好比vue组件中的data,所以声明state必须是纯粹的对象 (含有零个或多个的key/value
对),在建立后,State数据会被转换为响应式的数据。
3.1.1 State
的访问有以下的三种形式
- 在vue组件中(
tempalte
、data
、methods
、声明周期函数等)中访问 - 在vuex中访问
首先定义一个store,里面只包含State,然后我们将其注入到全局,下面一次进行以上三种形式的测试
//store.js
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
userName: "Vuex的学习之旅"
}
})
export default store
//main.js
import Vue from 'vue'
import App from './App.vue'
import store from "./store"
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store
}).$mount('#app')
//App.vue
<template>
<div id="app">
<test-component></test-component>
</div>
</template>
<script>
import TestComponent from "./components/test-component.vue"
export default {
name: "app",
components: { TestComponent }
}
</script>
1.在vue组件中访问
-
<template>
直接在模板中使用$store.state...
进行store中state数据的访问 -
<script>
通过this.$store.state...
进行store中state数据的访问
//test-component
<template>
<div id="app">
<div>姓名:{{ $store.state.userName }}</div>
</div>
</template>
<script>
export default {
name: 'test',
data() {
return {
username: this.$store.state.userName
}
},
created() {
console.log(this.$store.state.userName);
console.log(this.username);
}
}
</script>
注:由于不能修改store数据,所以一般不建议在data中访问store的数据,因为它没有缓存效果,一般在计算属性中获取state数据。
//test-component
<template>
<div id="app">
<div>姓名:{{ compute_username }}</div>
<div>{{ compute_age }}</div>
<div>{{ compute_sex }}</div>
</div>
</template>
<script>
export default {
name: 'test',
data() {
return {
description: "性别是"
}
},
computed: {
compute_username() {
return this.$store.state.userName
},
compute_age() {
return "年龄" + this.$store.state.age
},
compute_sex() {
return this.description + this.$store.state.sex
}
}
}
</script>
- 在vuex中访问
如果vuex中访问state的数据,一般是在mutation
、getters
中可以通过this.state...
进行获取
//store.js
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
userName: "Vuex的学习之旅"
},
mutations: {
set_userName(state, data) {
this.state.userName = data
//等同于 state.userName = data
}
}
})
export default store
//test-component
<template>
<div id="app">
<div>姓名:{{ $store.state.userName }}</div>
</div>
</template>
<script>
export default {
name: 'test',
data() {
return {
username: this.$store.state.userName
}
},
created() {
this.$store.commit("set_userName", "修改了vuex的名字")
}
}
</script>
3.1.2 mapState
语法糖
mapState
语法糖的主要作用是将store中的state映射到当前vue实例的computed中
在没有mapState
时,我们获取state一般在computed中进行获取,对于获取多个state数据,那么我们就要写多个computed方法,如下
//store.js
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
userName: "Vuex的学习之旅",
age: 18,
sex: "男"
}
})
export default store
//test-component
<template>
<div id="app">
<div>姓名:{{ compute_username }}</div>
<div>{{ compute_age }}</div>
<div>{{ compute_sex }}</div>
</div>
</template>
<script>
export default {
name: 'test',
data() {
return {
description: "性别是"
}
},
computed: {
compute_username() {
return this.$store.state.userName
},
compute_age() {
return "年龄" + this.$store.state.age
},
compute_sex() {
return this.description + this.$store.state.sex
}
}
}
</script>
针对于写多个computed的繁琐和冗余,使用mapState
可以帮助我们生成计算属性
。
3.1.2.1 mapState
对象写法
//test-component
<template>
<div id="app">
<div>姓名:{{ compute_username }}</div>
<div>{{ compute_age }}</div>
<div>{{ compute_sex }}</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'test',
data() {
return {
description: "性别是"
}
},
computed: mapState({
compute_username(state) {
return state.userName
//等同于return this.$store.state.userName
},
//ES6箭头函数
//compute_username:state => state.userName
//compute_username:state => this.$store.state.userName
// 传字符串参数 'age' 等同于 `state => state.age`
compute_age: 'age',
//需要配合组件实例中的其它数据,使用普通函数的形式,才能保证this的指向
compute_sex(state) {
return this.description + state.sex
}
})
}
</script>
3.1.2.1 mapState
数组写法
当映射的计算属性的名称与 state 的数据名称相同时,我们也可以给 mapState 传一个字符串数组。
<template>
<div id="app">
<div>姓名:{{ userName }}</div>
<div>{{ age }}</div>
<div>{{ sex }}</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'test',
data() {
return {
description: "性别是"
}
},
computed: {
userName() {
return this.$store.state.userName
},
age() {
return this.$store.state.age
},
sex() {
return this.$store.state.sex
}
}
}
</script>
<template>
<div id="app">
<div>姓名:{{ userName }}</div>
<div>{{ age }}</div>
<div>{{ sex }}</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'test',
data() {
return {
description: "性别是"
}
},
computed: mapState(["userName", "age", "sex"])
}
</script>
3.1.2.1 mapState
使用剩余展开运算符
mapState
返回的是一个对象,如果computed只包括mapState
,那么直接写
computed: mapState(["userName", "age", "sex"])
// 等同于
computed: {
...mapState(["userName", "age", "sex"])
}
如果你的computed还有其它store之外的属性,那么你需要使用剩余运算符,把mapState返回的对象和其它计算属性对象合并
<template>
<div id="app">
<div>姓名:{{ userName }}</div>
<div>{{ age }}</div>
<div>{{ sex }}</div>
<div>{{ getSexEnglishType }}</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'test',
data() {
return {
description: "性别是"
}
},
computed: {
...mapState(["userName", "age", "sex"]),
getSexEnglishType() {
return this.sex == "男" ? "boy" : "girl"
}
}
}
</script>