Vuex

官方解释

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式

储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测

方式发生变化。

状态管理到底是什么?

​ 可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。

管理什么状态呢?

比如用户的登录状态、用户名称、头像、地理位置信息等等。

比如商品的收藏、购物车中的物品等等。

这些状态信息,我们都可以放在统一的地方,对它进行保存和管理,而

且它们还是响应式的

单界面的状态管理

  • State:状态信息

  • View:视图层,可以针对State的变化,显示不同的信息

  • Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。

  • 案例分析:计数器

多界面状态管理

如果你的项目里有很多页面(组件/视图),页面之间存在多级的嵌套关系,此时,这些页面假如都需要共享一个状态的时候,此时就会产生以下两个问题:

  • 多个视图依赖同一个状态

  • 来自不同视图的行为需要变更同一个状态

    对于第一个问题,假如是多级嵌套关系,你可以使用父子组件传参进

解决,虽有些麻烦,但好在可以解决;对于兄弟组件或者关系更复杂

件之间,就很难办了,虽然可以通过各种各样的办法解决,可实在很不

优雅,而且等项目做大了,代码就会变成屎山,实在令人心烦。

​ 对于第二个问题,你可以通过父子组件直接引用,或者通过事件来变

更或者同步状态的多份拷贝,这种模式很脆弱,往往使得代码难以维护

  • 把各个组件都需要依赖的同一个状态抽取出来,在全局使用单例模式进行管理。
  • 在这种模式下,任何组件都可以直接访问到这个状态,或者当状态发生改变时,所有的组件都获得更新。

这就是 Vuex 背后的基本思想,借鉴了 Flux、Redux。与其他模式不同的

是,Vuex 是专门为 Vue 设计的状态管理库,以利用 Vue.js 的细粒度数

据响应机制来进行高效的状态更新。

Vuex的基本使用

安装

1
npm install vuex --save

配置vuex

在src路径下创建store文件夹,然后创建index.js文件,文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
state: {
// 定义一个name,以供全局使用
name: '张三',
// 定义一个number,以供全局使用
number: 0,
// 定义一个list,以供全局使用
list: [
{ id: 1, name: '111' },
{ id: 2, name: '222' },
{ id: 3, name: '333' },
]
},
});

export default store;

修改main.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import Vue from 'vue';
import App from './App';
import router from './router';
import store from './store'; // 引入我们前面导出的store对象

Vue.config.productionTip = false;

new Vue({
el: '#app',
router,
store, // 把store对象添加到vue实例上
components: { App },
template: '<App/>'
});

修改App.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div></div>
</template>

<script>
export default {
mounted() {
// 使用this.$store.state.XXX可以直接访问到仓库中的状态
console.log(this.$store.state.name);
}
}
</script>

官方建议我们以上操作this.$store.state.XXX最好放在计算属性中

1
2
3
4
5
6
7
8
9
10
export default {
mounted() {
console.log(this.getName);
},
computed:{
getName() {
return this.$store.state.name;
}
},
}

每次都写this.$store.state.XXX让你感到厌烦,你实在不想写这

个东西怎么办,当然有解决方案,就像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
<script>
import { mapState } from 'vuex'; // 从vuex中导入mapState
export default {
mounted() {
console.log(this.name);
},
computed: {
...mapState(['name']), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
},
}
</script>

可以在解构的时候给它赋别名,取外号,就像这样:

1
...mapState({ aliasName: 'name' }),  // 赋别名的话,这里接收对象,而不是数组

小案例

通过this.$store.commit(‘mutation中方法’)来修改状态

我们通过提交mutation的方式,而非直接改变store.state.count。

这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.count的值。

Vuex核心概念

  • Getters

    有时候,我们需要从store中获取一些state修饰后的状态,比如下面的Store中:

    获取学生年龄大于20的个数

    getters默认是不能传递参数的, 如果希望传递参数, 那么只能让getters本身返回另一个函数.

    比如上面的案例中,我们希望根据ID获取用户的信息

  • Mutation

    Vuex的store状态的更新唯一方式:提交Mutation

    Mutation主要包括两部分:

    ​ 字符串的事件类型(type)

    ​ 一个回调函数(handler),该回调函数的第一个参数就是state。

    mutation的定义方式:

    1
    2
    3
    4
    5
    mutation: {
    increment(state){
    state.count++
    }
    }

    通过mutation更新

    1
    2
    3
    increment: function(){
    this.$store.commit('incement')
    }

    Mutation传递参数

    参数被称为是mutation的载荷(Payload)

    Mutation中的代码

    1
    2
    3
    4
    5
    6
    7
    decrement(state,n){
    state.count -= n
    }

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

    多个参数

    通常会以对象的形式传递, 也就是payload是一个对象.

    1
    2
    3
    4
    5
    6
    7
    changeCount(state,payload){
    state.count = payload.count
    }

    changeCount: function(){
    this.$store.commit('changeCount',{count: 0})
    }

    另外一种提交方式

    1
    2
    3
    4
    5
    6
    7
    8
    this.$store.commit({
    type: 'changeCount',
    count: 1200
    })

    changeCount(state,payload){
    state.count = payload.count
    }

    Mutation响应规则

    当给state中的对象添加新属性时, 使用下面的方式:

    方式一: 使用Vue.set(obj, ‘newProp’, 123)

    方式二: 用新对象给旧对象重新赋值

    Mutations里面的函数必须是同步操作,不能包含异步操作!

  • Action

    Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.

    Action的基本使用代码如下:

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

    在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch

    同样的, 也是支持传递payload

    Action返回的Promise

  • Module

Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.当应用变得非常复杂时,store对象就有可能变得相当臃肿.为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters等.


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!