Vuex
定义
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
什么是“状态管理模式”
new Vue({
// state data () {
return {
count: 0 } }, // view template: ` <div>{
{ count }}</div> `, // actions methods: {
increment () {
this.count++ } } })
这里有一段代码,我们可以将它分为三个部分,即数据源、可视界面和行为;
这个状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
我们可以把它看作单向数据流,在actions中首先让变量count自增,然后在将自增后的值替换state中原来的值,最后将最新得到的值渲染到view界面中。
下面是“单向数据流”理念的简单示意图:

但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
为了更高效的解决上述问题,我们可以考虑把组件的共享状态抽取出来,以一个全局单例模式管理,在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为。这样通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。

优势
使用Vuex统一管理状态的好处:
- 能够在vuex中集中管理共享的数据,易于开发和后期维护
- 能够高效地实现组件之间的数据共享,提高开发效率
- 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步
使用场景
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。
1、当一个组件需要多次派发事件时
2、跨组件共享数据、跨页面共享数据
Vuex的基本使用
1. 安装vuex依赖包
npm install vuex --save
2. 导入vuex包
import Vuex from 'vuex' Vue.use(Vuex) //将vuex安装到项目中
3. 创建store对象
const store = new Vue.Store({
//state 中存放的就是全局的共享数据 state: {
count: 0 } })
4. 将store对象挂载到vue实例中
new Vue ({
el: '#app', render: h => h(app), //渲染app根组件 route, //挂载路由 //将创建的共享数据对象,挂载到Vue实例中 //所有的组件,就可以直接从store中获取全局的数据了 store })
Vuex的核心概念
State
State提供唯一的公共数据源,所有的共享的数据都要统一放到Store的State中进行存储。
//首先new一个Vuex.Store的构造函数从而得到了一个store的实例对象 const store = new Vue.Store({
//state 中存放的就是全局的共享数据 state: {
count: 0 } })
组件访问State中数据的方式:
this.$store.state.全局数据名称
例子:
这是store.js文件
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({
state: {
count: 0 } })
这是Add.vue文件
<template> <div> <!--通过插值表达式将数值显示在页面中--> <h3>当前最新的count值为:{
{$store.state.count}}</h3> </div> </template> <script> export default {
data() {
return {
} } } </script>
组件访问State中数据的第二种方式:
//1. 从vuex中按需导入mapState函数 import {
mapState } from 'vuex' //2. 通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性 computed: {
...mapState(['count']) }
例子:
这是Sub.vue文件
<template> <div> <h3>当前最新的count值为:{
{count}}</h3> </div> </template> <script> import {
mapState } from 'vuex' export default {
data() {
return {
} }, //定义一个计算属性,然后在计算属性中调用mapState函数 computed: {
//展开运算符, ...mapState(['count']), } } </script>
Mutations
Mutations用于变更Store中的数据。他有下面两种特点:
- 在vuex中,store中的数据是不可以直接更改的,必须通过提交mutation来改变store中的数据。
- 通过这种方法虽然操作起来有些繁琐,但是可以集中监控所有数据的变化。

例子:
//store.js //在state平级下面创建mutations,他后面对应一个对象,里面可以定义很多事件处理函数 export default new Vuex.Store({
state: {
count: 0 }, // 只有 mutations 中定义的函数,才有权利修改 state 中的数据 mutations: {
addN(state, step) {
state.count += step }, subN(state, step) {
state.count -= step } }, actions: {
}, getters: {
} })
//Add.vue <template> <div> <h3>当前最新的count值为:{
{$store.state.count}}</h3> <button @click="btnHandler1">+N</button> </div> </template> <script> export default {
data() {
return {
} }, methods: {
btnHandler1() {
//当我们点击按钮之后我们希望能调用全局中的AddN函数 // commit 的作用,就是调用 mutation中的某个函数 this.$store.commit('addN', 3) } } } </script>
this.$store.commit() 是触发mutation的第一种方式,还有第二种方式:
//1.从vuex中按需导入mapMutations函数 import {
mapMutations } from 'vuex' //2.将指定的mutations函数映射为当前组件的methods函数 methods: {
...mapMutations(['addN']) }
例子:
<template> <div> <h3>当前最新的count值为:{
{count}}</h3> <button @click="btnHandler1">-N</button> </div> </template> <script> //从vuex中按需导入mapMutations函数 import {
mapState, mapMutations} from 'vuex' export default {
data() {
return {
} }, computed: {
...mapState(['count']), }, methods: {
...mapMutations(['subN']), btnHandler1() {
this.subN(3) } } } </script>
Actions
当我们需要进行异步操作时,就要用到Action。Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
换句话说,如果想要通过异步操作变更数据,必须通过Action,而不能使用Mutation,但是在Action中还是要触发Mutation的方式来间接变更数据。

//store.js export default new Vuex.Store({
state: {
count: 0 }, // 只有 mutations 中定义的函数,才有权利修改 state 中的数据 mutations: {
addN(state, step) {
// 不要在 mutations 函数中,执行异步操作 // setTimeout(() => {
// state.count++ // }, 1000) state.count += step } }, actions: {
addNAsync(context, step) {
setTimeout(() => {
// 在 actions 中,不能直接修改 state 中的数据; // 必须通过 context.commit() 触发某个 mutation 才行 context.commit('addN', step) }, 1000) } }, getters: {
} })
//Add.vue <template> <div> <h3>当前最新的count值为:{
{$store.state.count}}</h3> <button @click="btnHandler">+N Async</button> </div> </template> <script> export default {
data() {
return {
} }, methods: {
btnHandler() {
// 这里的 dispatch 函数,专门用来触发 action this.$store.dispatch('addNAsync', 5) } } } </script>
this.$store.dispatch()是触发action的第一种方式,下面是第二种方式:
//1.从vuex中按需导入mapActions函数 import {
mapActions } from 'vuex' //2.将指定的actions函数映射为当前组件的methods函数 methods: {
...mapActions(['addNAsync']) }
<template> <div> <h3>当前最新的count值为:{
{count}}</h3> <button @click="btnHandler">-N</button> <!-- 可以省略btnHandler直接写addNAsync(3)--> <button @click="addNAsync(3)">-N</button> </div> </template> <script> //从vuex中按需导入mapMutations函数 import {
mapState, mapMutations, mapActions} from 'vuex' export default {
data() {
return {
} }, computed: {
...mapState(['count']), }, methods: {
...mapMutations(['addNAsync']), btnHandler() {
this.addNAsync(3) } } } </script>
Getters
Getter用于对Store中的数据进行加工处理形成新的数据。
- Getter 可以对Store中已有的数据加工处理之后形成新的数据,类似Vue的计算属性。
- Store 中数据发生变化,Getter 的数据也会跟着变化。


从vuex中按需导入mapGetters函数
将指定的getters函数映射为当前组件的computed函数
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/230542.html原文链接:https://javaforall.net
