Vuex介绍
为什么会有Vuex?
https://v3.vuex.vuejs.org/zh/
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vue是采用集中式管理组件依赖的共享数据的一个工具,可以解决不同组件数据共享问题
①Actions执行异步操作获取数据
②Actions commit 到 Mutations中执行同步操作去修改State中数据
③组件从State中读取数据
④组件再调用Actions,最终将四部操作连接起来
总结:
- 修改State状态必须通过Mutations
- Mutations只能执行同步代码,类似ajax,定时器之类的代码不能在Mutations中执行
- 执行异步代码,通过Actions,然后将数据提交给Mutations才可以完成
- State的状态即共享数据,可以再组件中引用
- 组件中可以调用Actions
Vuex使用
下载
yarn add vuex@3.5.1
src/store/index.js中创建vuex实例并对外暴露
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// ...
})
export default store
main.js中引入store并挂载到Vue实例上
import store from './store'
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
vuex–state
state放置所有公共状态的属性,如果你有一个公共状态数据,你只需要定义在state对象中
定义state
store/index.js
// 初始化vuex对象
const store = new Vuex.Store({
state: {
// 管理数据
count: 0
}
})
如何在组件中获取count?
在组件中获取count的两种方式
原始形式–插值表达式
Goods.vue
组件中可以使用 this.$store
获取到 vuex 中的 store 对象实例,可通过state属性获取count
<div>
state数据{{ $store.state.count }}
</div>
<script>
export default {
created() {
console.log(this.$store.state.count)
}
}
</script>
辅助函数–mapState
mapState是辅助函数,帮助我们把store中的数据映射到组件的计算属性中,属于一种方便用法
List.vue
① 导入mapState
② 采用数组形式引入state属性
③ 利用展开运算符将导出的状态映射给计算属性
<template>
<div>
List
{{ count }}
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
// 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组
// mapState 函数返回的是一个对象
// 使用对象展开运算符将此对象混入到外部对象中
...mapState(['count']),
// 类似于
// count() {
// return this.$store.state.count
// }
}
}
</script>
vuex-mutations
state数据的修改只能通过mutations,并且mutations必须是同步更新,目的是形成数据快照
数据快照:一次mutation的执行,立刻得到一种视图状态,所以必须是同步
定义mutations
store/index.js
// 初始化vuex对象
const store = new Vuex.Store({
state: {
// 管理数据
count: 70,
},
// 定义mutations
mutations: {
}
})
mutations是一个对象,对象中存放修改state的方法
// 定义mutations
mutations: {
// 方法里的参数 第一个参数是当前store的state属性
// 第二个参数 payload 运输参数 调用mutations时,可以传递参数
addCount(state) {
state.count += 1
},
addCountN(state, n) {
state.count += n
}
}
在组件中调用mutations的两种方式
原始形式 $store
Goods.vue
<template>
<div>
<button @click="addCount">+1</button>
</div>
</template>
<script>
export default {
methods: {
addCount() {
// 调用store中的mutations,提交给mutations
// commit('mutations方法名',参数)
this.$store.commit('addCount')
}
},
}
</script>
<style scoped></style>
带参数的传递
<button @click="addCountN(9)">+n</button>
methods: {
addCountN(n) {
this.$store.commit('addCountN', n)
}
},
辅助函数–mapMutations
mapMutations和mapState很像,把位于mutations中的方法提取出来,可以将它导入到methods中
List.vue
<template>
<div>
List
{{ count }}
<button @click="addCount">+1</button>
<button @click="addCountN(8)">+n</button>
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex';
export default {
computed: {
...mapState(['count']),
// 类似于
// count() {
// return this.$store.state.count
// }
},
methods: {
// 把位于mutations中的方法提取出来,可以将它导入到methods中
...mapMutations(['addCount', 'addCountN'])
},
}
</script>
<style scoped></style>
vuex-actions
state是存放数据的,mutations是同步更新数据,actions是负责进行异步操作
定义actions
store/index.js
actions: {
// 获取异步的数据 context 表示当前的store实例
// 可以通过 context.state 获取状态
// 也可以通过 context.commit 来提交 mutations
// 也可以通过 context.dispatch 调用其他的action
getAsyncCount(context) {
setTimeout(() => {
// 1秒后,要去修改state
context.commit('addCount')
}, 1000)
}
}
在组件中调用actions的两种方式
原始调用–$store.dispatch
<template>
<div>
<button @click="addAsyncCount">+1Async</button>
</div>
</template>
<script>
export default {
methods: {
addAsyncCount() {
this.$store.dispatch('getAsyncCount')
}
},
}
</script>
传参函数
- actions
actions: {
getAsyncCountN(context, n) {
setTimeout(() => {
// 1秒后,要去修改state
context.commit('addCountN', n)
}, 1000)
}
}
- 调用
<template>
<div>
<button @click="addAsyncCountN(6)">+nAsync</button>
</div>
</template>
<script>
export default {
methods: {
addAsyncCountN(m) {
this.$store.dispatch('getAsyncCountN', m)
}
},
}
</script>
辅助函数–mapActions
actions也有辅助函数,可以讲action导入到组件中
<template>
<div>
List
{{ count }}
<button @click="getAsyncCount">+1Async</button>
<button @click="getAsyncCountN(6)">+nAsync</button>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState(['count']),
// 类似于
// count() {
// return this.$store.state.count
// }
},
methods: {
...mapActions(['getAsyncCount', 'getAsyncCountN'])
},
}
</script>
<style scoped></style>
vuex-getters
除了state之外,有时还需从state中派生出一些状态,这些状态是依赖state的,会用到getters
state中定义了list数组,是1-10的数组
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
}
组件中需要显示大于5的数据,正常的方式,是需要list在组件中进行再一步的处理,但是getters可以帮助我们实现它
定义getters
getters: {
// getters函数第一个参数是state
// getters必须要有返回值
filterList: (state) => state.list.filter((item) => item > 5)
}
调用getters的两种方式
原始方式–getters
<ul>
<li v-for="(item, index) in $store.getters.filterList">{{ item }}</li>
</ul>
辅助函数–mapGetters
List.vue
<template>
<div>
List
{{ count }}
<ul>
<li v-for="(item, index) in filterList" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
export default {
computed: {
...mapState(['count']),
...mapGetters(['filterList'])
// 类似于
// count() {
// return this.$store.state.count
// }
},
methods: {
},
}
</script>
<style scoped></style>
总结
原始形式
简便形式
- state辅助函数映射到computed
- mutations辅助函数映射到methods
- actions辅助函数映射到methods
- getters辅助函数映射到computed
vuex-Module
为什么会有模块化
由于使用单一状态树,引用的所有状态会集中到一个比较大的对象,当应用变得非常复杂的时候,store对象就会变得非常臃肿
我们把所有的状态都放在state中,项目变得越来越大的时候,vuex会变得越来越难以维护,所以就需要Vuex模块化
模块化简单应用
- 定义两个模块 countModule 和 arrModule
- countModule 管理状态 count
- arrModule 管理状态 arr
store/index.js
import Vue from "vue"
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
countModule: {
state: {
count: 0,
}
},
arrModule: {
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
}
}
})
export default store
<template>
<div>
引入state中的数据---{{ $store.state.countModule.count }}
<hr>
<ul>
<li v-for="item in $store.state.arrModule.list">{{ item }}</li>
</ul>
</div>
</template>
注意:获取子模块的状态,通过 $store.state.模块名.属性名 来获取