一:什么是Vuex?
Vuex
是一个专为Vue.js
应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
二:vuex的核心
- Store:仓库,
Store
是使用Vuex
应用程序的核心,每个应用仅有一个Store
,它是一个容器,包含着应用中的大部分状态,当然我们不能直接改变Store
中的状态,我们要通过提交Mutations
的方式改变状态。 - State:状态,保存在
Store
中,因为Store
是唯一的,所以State
也是唯一的,称为单一状态树,这里的状态是响应式的。 - Getter:相当于
Vuex
中的计算属性,方便从一个属性派生出其他的值,它内部可以对计算的结果进行缓存,只有当依赖的状态发生改变的时候,才会重新计算。 - Mutation:状态的变化必须要通过提交
Mutation
来完成。 - Actions:与
Mutation
类似,不同的是可以进行异步的操作,内部改变状态的时候都需要改变Mutation
。 - Module:模块,由于使用的单一状态树让所有的状态都会集中到一个比较大的对象中,应用变得很复杂的时候,Store对象就会变得相当臃肿,为了解决这些问题
Vuex
允许我们将Store
分割成模块,每个模块拥有自己的State
,Mutation
,Actions
,Getter
,甚至是嵌套的子模块。
三:vuex的基本结构
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head' // 引入的module模块
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
state:{
name:'helloVueX'
},
mutations: {
},
actions: {
},
modules: {
ModuleHead
}
})
export default store
// main.js
import Vue from 'vue'
import App from './App.vue'
import 'style/comment.css'
import router from 'route/index'
import store from 'store/index' // 引入store文件
// ElementUI的引入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router,
store // 使用store
}).$mount('#app')
四:vuex的使用
1)state的使用
// demo.vue
<template>
<div>
<!-- 基础设施C -->
<span>$store.state获取vuex的值:{{$store.state.name}}</span>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
每次使用变量都要前面写$store.state
很是麻烦,所以这里使用Vuex
内部提供的mapState
的函数,会帮我们生成状态对应的计算属性
<template>
<div>
<!-- 基础设施C -->
<span>mapState获取vuex的值:{{name}}</span>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed:{
...mapState(['name'])
}
}
</script>
<style>
</style>
当然啦,我们也可以给获取的state
的值取别名的,和上面方法差不多,不同的是,mapState
参数是对象,键是别名,值是内容。
<template>
<div>
<!-- 基础设施C -->
<span>mapState获取vuex的值并设置别名:{{my_name}}</span>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed:{
...mapState({my_name:'name'}) // 参数是对象,键是别名,值是state对象里的值
}
}
</script>
<style>
</style>
2)Getter的使用
Vuex
中的getter
就相当于组件中的计算属性,如果想要对state
的数据进行简单的处理在展示,可以使用getter
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
state:{
name:'helloVueX',
my_name: '老哥'
},
getters:{
mapData({my_name}) { // 参数是state对象,这里把my_name解构出来了
return `我是经过改造的${my_name}`
}
},
mutations: {
},
actions: {
},
modules: {
ModuleHead
}
})
export default store
<template>
<div>
<!-- 基础设施C -->
<span>{{$store.getters.mapData}}</span>
</div>
</template>
<script>
export default {
computed:{
}
}
</script>
<style>
</style>
同样那样引用过于麻烦,那么和mapState
一样,使用内部的mapGetters
,也是将其映射到组件的计算属性,其用法和mapState
一样,也可以为了避免冲突使用对象设置别名
<template>
<div>
<!-- 基础设施C -->
<span>mapGetters取值:{{mapData}}</span>
<br>
<span>mapGetters取值并取别名:{{another_name}}</span>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed:{
...mapGetters(['mapData']),
...mapGetters({ another_name:'map_data'})
}
}
</script>
<style>
</style>
3)Mutation的使用
状态的修改必须提交Mutation
,Mutation
必须是同步执行的。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
state:{
name:'helloVueX',
my_name: '老哥',
age:0
},
getters:{
mapData({my_name}) {
return `我是经过改造的${my_name}`
},
map_data({my_name}) {
return `${my_name}有别名的`
}
},
mutations: {
// 第一个参数是store,
//此处需要对store对象的值进行修改,不可以解构里面的变量,要写全
// 不能写成addStoreAge({age},payload)的形式
// 第二个参数是提交的参数
addStoreAge(store,payload) {
store.age += payload
},
desStoreAge(store,payload) {
if (store.age > 0) {
store.age -= payload
}
}
},
actions: {
},
modules: {
ModuleHead
}
})
export default store
// demo.vue
<template>
<div>
<!-- 基础设施C -->
<button @click="$store.commit('desStoreAge',2)">减2</button>
<input v-model="$store.state.age"/>
<button @click="$store.commit('addStoreAge',2)">加2</button>
</div>
</template>
<script>
export default {
computed:{
}
}
</script>
<style>
</style>
同样那样引用过于麻烦,那么和mapState
一样,使用内部的mapMutations
,使用map
方法将当前的mutation
映射到methods
中,其依旧会返回一个对象,这个对象中存储的是mutation
中映射的方法
<template>
<div>
<!-- 基础设施C -->
<button @click="des(2)">减2</button>
<input v-model="age"/>
<button @click="add(2)">加2</button>
</div>
</template>
<script>
import {mapMutations,mapState} from 'vuex'
export default {
computed:{
...mapState(['age'])
},
methods:{
// ...mapMutations(['desStoreAge','addStoreAge'])
...mapMutations({des:'desStoreAge',add:'addStoreAge'}) // 起别名
}
}
</script>
<style>
</style>
4)Actions的使用
如果有异步的修改,需要使用actions
,在actions
中可以执行异步操作,当异步操作结束后,如果需要更改状态,还需要提交Mutation
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
state:{
name:'helloVueX',
my_name: '老哥',
age:0
},
getters:{
mapData({my_name}) {
return `我是经过改造的${my_name}`
},
map_data({my_name}) {
return `${my_name}有别名的`
}
},
mutations: {
// 第一个参数是store,
//此处需要对store对象的值进行修改,不可以解构里面的变量,要写全
// 不能写成addStoreAge({age},payload)的形式
// 第二个参数是提交的参数
addStoreAge(store,payload) {
store.age += payload
},
desStoreAge(store,payload) {
if (store.age > 0) {
store.age -= payload
}
}
},
actions: {
// 第一个参数是context上下文,这个对象中有state,commit,getters等成员
// 第二个参数是payLoad
addStoreAgeAsync({commit},payload) {
setTimeout(() => { // 延迟两秒,模拟异步操作
commit('addStoreAge',payload)
}, 2000);
},
desStoreAgeAsync({commit},payload) {
setTimeout(()=> {
commit('desStoreAge',payload)
},2000)
}
},
modules: {
ModuleHead
}
})
export default store
<template>
<div>
<!-- 基础设施C -->
<button @click="$store.dispatch('desStoreAgeAsync',2)">减2</button>
<input v-model="age"/>
<button @click="$store.dispatch('addStoreAgeAsync',2)">加2</button>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed:{
...mapState(['age'])
},
methods:{
}
</script>
<style>
</style>
结果是:点击按钮2秒后,值才会被修改
同样的,actions
也有对应的mapActions
,不需要使用如上面的方法dispatch
<template>
<div>
<!-- 基础设施C -->
<button @click="des(2)">减2</button>
<input v-model="age"/>
<button @click="add(2)">加2</button>
</div>
</template>
<script>
import {mapState,mapActions} from 'vuex'
export default {
computed:{
...mapState(['age'])
},
methods:{
// ...mapActions(['desStoreAgeAsync','addStoreAgeAsync'])
...mapActions({des:'desStoreAgeAsync',add:'addStoreAgeAsync'})
}
}
</script>
<style>
</style>
5)Modules的使用
模块可以让我们把单一状态树拆分成多个模块,每个模块都可以拥有自己的state
,mutation
,action
,getter
甚至嵌套子模块。
模块定义
在store
文件夹中,创建一个modules
文件夹,里面每一个js文件就是一个模块,下面是每一个模块的定义格式
// head.js,这里定义值
let headData = [
{
lable: '基础设施1',
value: 'infrastructureA',
path: 'tab_a'
},
{
lable: '基础设施2',
value: 'infrastructureB',
path: 'tab_b'
},
{
lable: '基础设施3',
value: 'infrastructureC',
path: 'tab_c'
},
{
lable: '基础设施4',
value: 'infrastructureD',
path: 'tab_d'
},
{
lable: '基础设施5',
value: 'infrastructureE',
path: 'tab_e'
}
]
export {
headData
}
注意:子模块需要使用命名空间namespaced: true
,否则是找不到的
// modules/head/index.js // 子模块
import {headData} from './head'
let head_store = {
// 命名空间
namespaced: true,
state:{
headData,
name: null,
userInfo: null
},
mutations: {
login(state,payload) {
state.name= payload.my_name
},
saveInfo(state,payload) {
console.log('异步修改state:',state)
console.log('异步修改payload:',payload)
state.userInfo= payload
}
},
actions: {
//异步修改
asyncSaveInfo({commit},data) {
commit('saveInfo',data)
}
},
modules: {
}
}
export default head_store
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
state:{
name:'helloVueX',
my_name: '老哥',
age:0
},
getters:{
mapData({my_name}) {
return `我是经过改造的${my_name}`
},
map_data({my_name}) {
return `${my_name}有别名的`
}
},
mutations: {
// 第一个参数是store,
//此处需要对store对象的值进行修改,不可以解构里面的变量,要写全
// 不能写成addStoreAge({age},payload)的形式
// 第二个参数是提交的参数
addStoreAge(store,payload) {
store.age += payload
},
desStoreAge(store,payload) {
if (store.age > 0) {
store.age -= payload
}
}
},
actions: {
// 第一个参数是context上下文,这个对象中有state,commit,getters等成员
// 第二个参数是payLoad
addStoreAgeAsync({commit},payload) {
setTimeout(() => { // 延迟两秒,模拟异步操作
commit('addStoreAge',payload)
}, 2000);
},
desStoreAgeAsync({commit},payload) {
setTimeout(()=> {
commit('desStoreAge',payload)
},2000)
}
},
modules: {
ModuleHead // 引入子模块
}
})
export default store
使用子模块headData
的数据
<template>
<div>
<!-- 基础设施C -->
<p v-for="(item,index) in $store.state.ModuleHead.headData" :key="index">
{{item.lable}}
</p>
</div>
</template>
<script>
export default {
computed:{
},
methods:{
}
}
</script>
<style>
</style>
同样的,我们也可以使用mapState
、mapMutations
等
<template>
<div>
<!-- 基础设施C -->
<p v-for="(item,index) in headData" :key="index">
{{item.lable}}
</p>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed:{
...mapState('ModuleHead',['headData'])
},
methods:{
}
}
</script>
<style>
</style>
五:Vuex严格模式
所有的状态变更必须提交mutation
,但是如果在组件中获取到$store.state.msg
进行修改,语法层面没有问题,却破坏了Vuex
的约定,且devTools
也无法跟踪到状态的修改,开启严格模式之后,如果在组件中直接修改state
,会报错。
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
strict: true, // 开启严格模式
state:{
name:'helloVueX',
my_name: '老哥',
age:2
},
getters:{
mapData({my_name}) {
return `我是经过改造的${my_name}`
},
map_data({my_name}) {
return `${my_name}有别名的`
}
},
mutations: {
// 第一个参数是store,
//此处需要对store对象的值进行修改,不可以解构里面的变量,要写全
// 不能写成addStoreAge({age},payload)的形式
// 第二个参数是提交的参数
addStoreAge(store,payload) {
store.age += payload
},
desStoreAge(store,payload) {
if (store.age > 0) {
store.age -= payload
}
}
},
actions: {
},
modules: {
ModuleHead
}
})
export default store
<template>
<div>
<!-- 基础设施C -->
<button @click="$store.state.age -= 2">des</button>
<input v-model="age"/>
<button @click="$store.state.age += 2">add</button>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed:{
...mapState(['age'])
},
methods:{
}
}
</script>
<style>
</style>
注意:
strict:false
是非严格模式,默认是false
,可以直接通过$store.state.age
来进行修改- 不要在生产环境开启严格模式,因为严格模式会深度检测状态树,会影响性能。在开发模式中开启严格模式,在生产环境中关闭严格模式
export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
state: {
...
}
vuex插件
会在每个 mutation
完成后调用,接收 mutation
和经过 mutation
后的状态作为参数
代码如下:
// plugin.js
export function my_plugin(store) {
store.subscribe((mutation,state) => {
console.log('mutation==',mutation.type)
console.log('state==',state)
})
}
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import ModuleHead from './modules/head'
import {my_plugin} from './Plugin'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
strict: true,
plugins:[my_plugin],
state:{
name:'helloVueX',
my_name: '老哥',
age:2
},
getters:{
mapData({my_name}) {
return `我是经过改造的${my_name}`
},
map_data({my_name}) {
return `${my_name}有别名的`
}
},
mutations: {
// 第一个参数是store,
//此处需要对store对象的值进行修改,不可以解构里面的变量,要写全
// 不能写成addStoreAge({age},payload)的形式
// 第二个参数是提交的参数
addStoreAge(store,payload) {
console.log('触发addStoreAge')
store.age += payload
},
desStoreAge(store,payload) {
console.log('触发desStoreAge')
if (store.age > 0) {
store.age -= payload
}
}
},
actions: {
},
modules: {
ModuleHead
}
})
export default store
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!