简介

官方文档

Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

在这里有一个名词状态管理,个人的理解是:把网站比喻成一个对象,在网站上进行的各种操作,调用某些接口来修改指定的信息,而这些被修改的信息可以称之为网站的状态,状态管理相当于用一个较为方便的插件/组件来对其进行修改。

如何开始?

官方提供了多种导入方式

  1. 直接引用 cdnhttps://unpkg.com/vuex@4.0.0/dist/vuex.global.js
  2. npm 安装:npm install vuex@next --save
  3. yarn 安装: yarn add vuex@next --save

使用

  1. 创建一个新的 store 文件夹,在 store 文件夹下面再创建一个 index.js 来作为整个 vuex 文件的入口

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

    Vue.use(Vuex);

    const store = new Vuex.Store({
    state: {
    // 定义应用程序的状态
    // 例如:user: null,
    },
    mutations: {
    // 定义修改状态的方法
    // 例如:SET_USER(state, user) { state.user = user; }
    },
    actions: {
    // 定义处理异步操作的方法
    // 例如:fetchUser({ commit }) { API.fetchUser().then(user => commit('SET_USER', user)); }
    },
    getters: {
    // 定义计算派生状态的方法
    // 例如:isLoggedIn(state) { return state.user !== null; }
    },
    });
  2. 在组件中如果想要使用的话,直接 this.$store.state.user 就可以读取 user 的状态了

属性说明

state

这里面存放各个状态对象的属性值,这些属性值可以是整数、字符串、数组、对象等等。如果想要修改这里面的属性值的话一般由 mutation 来提交修改。

mutations

这个部分书写一些对于 state 修改的操作。
在组件想要提交这种修改的话可以通过 this.$store.commit('xxx') 来提交修改,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { mapMutations } from 'vuex';

export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

// `mapMutations` 也支持载荷:
'incrementBy', // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment', // 将 `this.add()` 映射为 `this.$store.commit('increment')`
}),
},
};

通过上面的映射之后,可以看出下面两种写法是等价的

1
2
3
4
5
6
7
8
export default {
// ...
methods: {
func() {
this.$store.commit('increment', 10);
},
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

// `mapMutations` 也支持载荷:
'incrementBy', // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
func() {
this.increment(10);
},
},
};

而在 store 里面,mutation 的写法是这样子的:

1
2
3
4
5
mutations: {
increment (state) {
state.count++
}
}
1
2
3
4
5
mutations: {
increment (state, n) {
state.count += n
}
}

action

action 类似于 mutation

查看不同
  1. action 提交的是 mutation,而不是直接变更状态。
  2. action 可以包含任意异步操作。

简单注册一个action

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const store = createStore({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++;
},
},
actions: {
increment(context) {
context.commit('increment');
},
},
});

注册

在里面也可以使用 ES6 解构 进行简化

1
2
3
4
5
actions: {
increment ({ commit }) {
commit('increment')
}
}

在注册 action 的处理函数总是接受 context 作为第一个参数,payload 作为第二个参数(可选),context 对象包含以下属性:

1
2
3
4
5
6
7
8
{
state, // 等同于 `store.state`,若在模块中则为局部状态
rootState, // 等同于 `store.state`,只存在于模块中
commit, // 等同于 `store.commit`
dispatch, // 等同于 `store.dispatch`
getters, // 等同于 `store.getters`
rootGetters; // 等同于 `store.getters`,只存在于模块中
}

调用

在组件可以通过 dispatch 方法触发

1
store.dispatch('increment');

同时也可以采用类似上面的说的辅助函数 mapActions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { mapActions } from 'vuex';

export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

// `mapActions` 也支持载荷:
'incrementBy', // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment', // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
}),
},
};

getter

相当于是 store 的计算属性,也可以理解成 vue 组件中的computed 属性,只不过它只用来计算 store 里面的属性,它接收 state 作为第一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
const store = createStore({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false },
],
},
getters: {
doneTodos(state) {
return state.todos.filter((todo) => todo.done);
},
},
});

它还有多种访问的方式:

  1. 通过属性访问

    1
    store.getters.doneTodos; // -> [{ id: 1, text: '...', done: true }]
  2. 通过方法访问

    1
    2
    3
    4
    5
    6
    getters: {
    // ...
    getTodoById: (state) => (id) => {
    return state.todos.find((todo) => todo.id === id);
    };
    }
    1
    store.getters.getTodoById(2); // -> { id: 2, text: '...', done: false }
  3. 辅助函数mapGetters

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import { mapGetters } from 'vuex';

    export default {
    // ...
    computed: {
    // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
    'doneTodosCount',
    'anotherGetter',
    // ...
    ]),
    },
    };

好了,今天的 vuex 初步认识就到这里啦,如果上面说的有错误欢迎在下面评论区进行说明