VueX(Vue状态管理模式)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VueX(Vue状态管理模式)相关的知识,希望对你有一定的参考价值。

参考技术A

VueX 是适用于在 Vue 项目开发时使用的状态管理工具。试想一下,如果在一个项目开发中频繁的使用组件传参的方式来同步 data 中的值,一旦项目变得很庞大,管理和维护这些值将是相当棘手的工作。为此, Vue 为这些被多个组件频繁使用的值提供了一个统一管理的工具—— VueX 。在具有 VueX 的Vue项目中,我们只需要把这些值定义在VueX中,即可在整个Vue项目的组件中使用。

由于 VueX 是在学习 VueCli 后进行的,所以在下文出现的项目的目录请参照 VueCli 2.x 构建的目录。

以下步骤的前提是你已经完成了Vue项目构建,并且已转至该项目的文件目录下。

打开main.js

例如在App.vue中,我们要将state中定义的name拿来在h1标签中显示

或者要在组件方法中使用

注意,请不要在此处更改 state 中的状态的值,后文中将会说明

在Vue项目开发中,需要监控项目中得各种值,为了提高效率,Vue提供了一款浏览器扩展——VueDevtools。

在学习VueX时,更为需要使用该插件。关于该插件的使用可以移步官网,在此不再赘叙。

在VueX对象中,其实不止有 state ,还有用来操作 state 中数据的方法集,以及当我们需要对 state 中的数据需要加工的方法集等等成员。

成员列表:

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

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

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

mutations 是操作 state 数据的方法的集合,比如对该数据的修改、增加、删除等等。

mutations 方法都有默认的形参:

( [state] [,payload] )

例如,我们编写一个方法,当被执行时,能把下例中的name值修改为 "jack" ,我们只需要这样做

index.js

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

在实际生产过程中,会遇到需要在提交某个 mutation 时需要携带一些参数给方法使用。

单个值提交时:

当需要多参提交时,推荐把他们放在一个对象中来提交:

接收挂载的参数:

另一种提交方式

为了配合Vue的响应式数据,我们在Mutations的方法中,应当使用Vue提供的方法来进行操作。如果使用 delete 或者 xx.xx = xx 的形式去删或增,则Vue不能对数据进行实时响应。

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

Getters中的方法有两个默认参数

例如

组件中调用

由于直接在 mutation 方法中进行异步操作,将会引起数据失效。所以提供了Actions来专门进行异步操作,最终提交 mutation 方法。

Actions 中的方法有两个默认参数

例如,我们在两秒中后执行 2.2.2 节中的 edit 方法

由于 setTimeout 是异步操作,所以需要使用 actions

在组件中调用:

改进:

由于是异步操作,所以我们可以为我们的异步操作封装为一个 Promise 对象

当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex 允许我们将 store 分割成 模块(module) 。每个模块拥有自己的 state、mutation、action、getter 、甚至是嵌套子模块——从上至下进行同样方式的分割。

组件内调用模块a的状态:

而提交或者 dispatch 某个方法和以前一样,会自动执行所有模块内的对应 type 的方法:

如果把整个 store 都放在 index.js 中是不合理的,所以需要拆分。比较合适的目录格式如下:

对应的内容存放在对应的文件中,和以前一样,在 index.js 中存放并导出 store 。 state 中的数据尽量放在 index.js 中。而 modules 中的 Astore 局部模块状态如果多的话也可以进行细分。

Vue中状态管理——Vuex

vuex是一个专门为vue.js设计的状态管理模式,并且也可以使用devtools进行调试。

在vuex出现之前,vue里面的状态是属于‘单向数据流’。举个官网的例子:

new Vue({
    // state
    data () {
        return {
            count: 0
        }
    },
    // view
    template: `<div>{{ count }} </div`,
    // actions
    methods: {
        increment () {
            this.count++
        }
    }
})

其中

  • state是一个数据源
  • view以声明的方式将state映射到视图
  • actions 响应在view上的用户输入导致的状态变化
    这里写图片描述

但是解决不了 多个组件共享状态

所以vuex应运而生

这里写图片描述

简单来说,就是共享的状态用state来存放,用mutations来操作state,但是需要用store.commit来主动式的操作mutations。

下面来单独介绍 state,getters,mutations,actions,modules

State

单一状态树
vuex使用单一状态树,那么就可以用一个对象来包含全部的应用层级状态。所以state就作为数据源。
如何在组件中获得vuex状态?
由于vuex的状态存储是响应式的,所以从store实例中读取状态的最简单方法就是使用计算属性来返回某个状态:

这个是store/state.js中声明的数据源
这里写图片描述

这个是在组件中进行的引用
这里写图片描述

不过需要注意的是,在组件中进行引用之前,需要先在入门文件中进行注入
即:
这里写图片描述

如果不在根实例中注册store选项的话,那么需要在每一个使用state的组件中都要导入。

注册之后,子组件只需要this.$store即可调用vuex。

Getters

有时候我们需要从state中派生出一些状态,比如筛选一组列表,并且这个筛选后的数据是有其他组件要用的。那么我们就需要把这个结果进行包装,形成共享状态。
例如:

computed:{
    doneTodosCount () {
        return this.$store.state.todos.filter(todo => todo.done).length
    }
}

如果说这个length是其他组件用的话,那么如何做呢?

Getter就这样应运而生了。

getters: {
    doneTodosCount: state => {
        return state.todos.filter(todo => todo.done).length
    }
}

Getter 会暴露为store.getters对象

所以很容易在任何组件中使用它:

computed: {
    doneTodosCount () {
        return this.$store.getters.doneTodosCount
    }
}

这是getters.js

这里写图片描述

这是组件中的引用
这里写图片描述

Mutations

更改Vuex的store中的状态的唯一方法就是提交mutations。
Vuex中的mutations就像一个事件:每个mutations都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数接受state作为第一个参数。

但是我们又不能直接来调用一个mutations的handler。要唤醒一个mutations handler,需要以相应的type来调用store.commit方法。

这个是在mutations.js中注册的一些的事件

这里写图片描述

这是在组件中来触发这个事件

当然,我们注意到,mutations中可以传递额外的参数,这个参数就叫做mutations的载荷。
在更多的情况下,载荷应该是一个对象。这样可以包含更多的字段。

但是mutations必须是同步函数。

那我们如何来异步的更新State呢?

答案是: Actions

Actions

Actions类似于 mutations 不同的是:

  • Actions 提交的是mutations,而不是直接变更状态。
  • Actions 可以包含任意异步操作。

这也就形成了 actions —— mutations —— state 的过程

Actions函数接受一个与store实例具有相同方法和属性的context对象,因此可以通过context.commit来提交一个mutations。但是如何触发呢?

答案: store.dispatch

这里写图片描述

这里写图片描述
这里写图片描述

Modules

使用单一状态树,导致应用的所有状态都集中到了一个很大的对象。所以,store对象容易变得臃肿。

为了解决这个问题, Vuex允许咱们把store进行一个功能拆分,分割成不同的模块(module)。每个模块都拥有自己的store,mutations,action,getters。

项目结构

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

总结:

vuex可以用在单页面上的组件间共享状态。不适合用于跨页面的通信。
另外,对于一些跨页面的数据或者关键性的数据,可以通过localStorage,sessionStorage

以上是关于VueX(Vue状态管理模式)的主要内容,如果未能解决你的问题,请参考以下文章

Vue状态管理vuex

Vue状态管理vuex

理解Vue的状态管理模式Vuex

Vue状态管理之Vuex

VueX(Vue状态管理模式)

Vue笔记(Vuex全局状态管理器)