Vuex:vue的状态管理模式

417 阅读3分钟

一、前言

官方介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

个人主观理解:可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。然后,将这个对象放在顶层的Vue实例中,这样,多个组件就可以共享这个对象中的所有变量属性了。并且是响应式的,这样就非常便利了

先说说Vuex主要用来管理什么状态:

  • 比如用户的登录状态、用户名称、头像、地理位置信息等等。
  • 比如商品的收藏、购物车中的物品等等。 这些状态信息,我们都可以放在统一的地方,对它进行响应式的保存和管理。

二、使用

此时你的项目的src文件夹应当是这样的

App.vue
│  main.js
│
├─assets
│      logo.png
│
├─components
│      HelloWorld.vue
│
├─router
│      index.js
│
└─store
       index.js

2.1初始化store下index.js中的内容

先创建一个文件夹store,并且在其中创建一个index.js文件 在index.js文件中写入代码如下图:

2.2将store挂载到当前项目的Vue实例当中去

为了让所有的Vue组件都可以使用这个store对象。

  • 打开main.js文件,导入store对象,并且放在new Vue中 这样,在其他Vue组件中,我们就可以通过this.$store的方式,获取到这个store对象了

2.3 在组件中使用Vuex

  • 通过this.$store.state.属性的方式来访问状态
  • 通过this.$store.commit('mutation中方法')来修改状态
注意事项:
我们通过提交mutation的方式,而非直接改变store.state.count。
这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.count的值。(需要使用devtools插件)

三、Vuex的核心内容

全局单例模式(可理解为一个大管家) 我们现在要做的就是将共享的状态抽取出来,交给我们的大管家,统一进行管理。 之后,你们每个试图,按照我规定好的规定,进行访问和修改等操作。 这就是Vuex背后的基本思想。

成员列表:

  • state 存放状态
  • getters 加工state成员给外界
  • mutations state成员操作
  • actions 异步操作
  • modules 模块化状态管理

3.1下面是Vuex官网给出的流程图:

Vuex官网给出的流程图

  • 首先,Vue组件如果调用某个VueX的方法过程中需要向后端请求时或者说出现异步操作时,需要dispatch VueX中actions的方法,以保证数据的同步。可以说,action的存在就是为了让mutations中的方法能在异步操作中起作用。

  • 如果没有异步操作,那么我们就可以直接在组件内提交状态中的Mutations中自己编写的方法来达成对state成员的操作。官方不建议在组件中直接对state中的成员进行操作,这是因为直接修改(例如这是错误的:this.$store.state.name = 'helloworld' )的话不能被VueDevtools所监控到。

最后被修改后的state成员会被渲染到组件的原位置当中去。

3.2Getters基本使用

可以对state中的成员加工后传递给外界

  • Getters中的方法有两个默认参数:
  1. state 当前VueX对象中的状态对象
  2. getters 当前getters对象,用于将getters下的其他getter拿来用

例子:获取students中年龄大于20的个数 state原始值

在Store中定义getters

在组件的computed中调用

3.3Mutations的基本使用

3.3.1mutations传递参数

mutations方法都有默认的形参:([state], [payload])

  • state是当前VueX对象中的state
  • payload是该方法在被调用时传递参数使用的

index.js中mutation的定义方式:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.store({
    state:{
        count:1,
        name : liduhui
    },
    mutations:{
        //es6语法,等同increment:funcion(){...}
        increment(state,n) {
            state.count +=n
        }
    }
})

export default store

接着在组件中,我们需要这样去调用这个mutation——例如在App.vue的某个method中:

increment:function() {
    this.$store.commit('increment',2)
}

当然payload也可以是个对象写法如下:(用changeCount代替increment)

定义:
chengeCount(state,payload) {
    state.count = payload.count,
    state.name = payload.name
}
使用:(第一种commit风格)
changeCount: function() {
    this.$store.commit('changeCount',{count: 100,name: LDH})
}

3.3.2mutations另一种提交风格:

  • 上面的通过commit进行提交是一种普通的方式
  • Vue还提供了另外一种风格,它是一个包含type属性的对象
在组件中,我们需要这样去调用这个mutation的另一种commit风格:
this.$store.commit({
    type: 'changCount',
    count: 100,
    name: LDH
})

3.3.2mutations响应规则

Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新. 这就要求我们必须遵守一些Vuex对应的规则:

  • 增加属性
  1. 提前在store中初始化好所需的属性.
  2. 当给state中的对象添加新属性时, 使用下面的方式:
  • 方式一: 使用Vue.set(state, 'name', homiry)
  • 方式二: 用新对象给旧对象重新赋值 用例子说明:
  • 当我们点击更新信息时, 界面并没有发生对应改变

  • 两种可以让state中的属性是响应式的方式

  • 删除成员

Vue.delete(state,'name')

注意:通常情况下, Vuex要求我们Mutation中的方法必须是同步方法。 主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照。 但是如果是异步操作, 那么devtools将不能追踪这个操作什么时候会被完成.

3.4Actions的使用

上面说了不要再Mutation中进行异步操作但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求, 这时就用Actions了

  • 先举个例子先说明一下context是什么?

context是和store对象具有相同方法和属性的对象. 也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等. 但是注意, 这里它们并不是同一个对象

  • 在组件中使用Actions

  • Actions进行异步处理例子:

###3.5Modules 当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters等

3.5.1module局部状态

上面的代码中, 我们已经有了整体的组织结构, 下面我们来看看具体的局部模块中的代码如何书写。

  • 在moduleA中添加state、mutations、getters
  • mutation和getters接收的第一个参数是局部状态对象

在module文件夹下的moduleA.js中

在App.vue中

注意:

  • 虽然, 我们的doubleCount和increment都是定义在对象内部的.
  • 但是在调用的时候,依然是通过this.$store来直接调用的.

3.5.2actions的写法

局部状态通过 context.state暴露出来,根节点状态则为 context.rootState

如果getters中也需要使用全局的状态, 可以接受更多的参数

四、目录规范

│
└─store                     #创建store文件夹
       index.js             #组装模块并导出store
       actions.js           #根级别的action
       mutations.js         #根级别的mutations
       mutations_type.js   ##该项为存放mutaions方法常量的文件,按需要可加入
       getters.js
       modules              #modules文件夹
            ModulesA.js     
            ModulesB.js