目录

一、vuex简介

1.1 vuex是什么

1.2 什么时候使用Vuex

二、Vuex工作原理图

2.1 官方vuex工作原理图

2.2 Vuex工作流程

三、搭建Vuex环境

3.1 安装

3.2 引用Vuex

四、案例练习 - 求和案例

4.1 Count.vue 

4.2 App.vue

4.3 index.js


一、vuex简介

1.1 vuex是什么

概念:专门在Vue中实现集中状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式管理(读/写),也是一中组件间通信的方式,且适用于任意组件间通信

vuex

1.2 什么时候使用Vuex

  1. 多个组件依赖同一状态
  2. 来自不同组件的行为需要变更同一状态

二、Vuex工作原理图

2.1 官方vuex工作原理图

每一个 Vuex 应用的核心就是 store,里面又包括:

1. State(状态):用于数据的存储(对象类型数据),是store中唯一数据源

2. Actions(行为):类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步事件

3. Mutations(转变):类似函数,改变state数据的唯一途径,且不能用于处理异步事件。

Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方

4. Getter(数据加工):如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关计算

5. Module:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

2.2 Vuex工作流程

(1) vcvue组件)通过调用 store dispatch方法,派发给actions执行actions可以继续通过调用dispatch方法给自身派发另一个actions,也可以调用异步方法(Backend API

(对应原理图:Vue Components -> Dispatch -> Acitons


(2)acitons调用 store 中的 commit方法,由 actions 提交一个 mutation

(对应原理图:Actions  -> Commit -> Mutation

如果vcvue组件)与 actions 之间没有业务逻辑,也可以直接由vcvue组件)提交一个 mutation

(即Vue Components -> Commit -> Mutation


(3)mutations去更新state中的数据,不需要手动执行(Mutate 不是一个API,不用去调用),由mutations的回调函数内对应的代码片段自动执行(执行后底层自动走Mutate)。

一般是由mutations更新state中的数据,在此处可以被开发者工具(Devtools)直接监控

对应原理图:Mutation  -> Mutate -> State

因为actions.context中也包含了state,可由actions去更新state中的数据,不经过mutation因而不被开发者工具(Devtools)监控,但不提倡这么做

(即Actions  -> Mutate ​​​​​​​-> State


(4)state中的数据更新之后,就会通知vue进行渲染

对应原理图:State -> Render -> Vue Components


组件中读取vuex中的数据:

$store.state.自定义的数据名 // 在vuex中index.js文件中state内定义的数据

组件中修改vuex中的数据:

$store.dispath('action中的方法名',数据)
或
$store.commit('mutation中的方法名',数据)

 注意:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

三、搭建Vuex环境

3.1 安装

终端安装

npm i vuex

注意:

  • 2022.2.7,vue3称为了默认版本,即在终端执行 npm i vue,默认安装的是vue3版本,而vuex也更新到4版本,所以 终端执行 npm i vuex 默认安装的是vuex4
  • vuex4 只能在 vue3中使用,而vue2中,要用的是vuex的3版本

所以如果用的是vue2的话,则需要安装vuex的3版本,在终端执行:

npm i vuex@3

3.2 引用Vuex

1. 创建文件:src/store/index.js

// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);

// 准备actions对象 - 响应组件中用户的动作
const actions = {};
// 准备mutations对象 - 修改state中的数据
const mutations = {};
// 准备state对象 - 保存具体数据
const states = {};

// 创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
});

2. 在main.js中创建vm时传入store配置项

// 引入Vue
import Vue from "vue";
// 引入App
import App from "./App.vue";
// 引入store配置项
import store from "./store";

Vue.config.productionTip = false;

// 创建vm
new Vue({
  el: "#app",
  render: (h) => h(App),
  store,
  // 安装全局事件总线
  beforeCreate() {
    Vue.prototype.$bus = this;
  },
});

如何验证是否成功引入store配置项?即可控制台输出组件实例对象,找到$store即为成功引入

注意:至于为何引入Vuex是在 src/store/index.js 中引入,而非在 main.js 中直接引入使用

  • 因为 import 引入模块或者文件,在执行时,默认是放在文件最前端优先执行的。而当我们在main.js中引入store配置项时,先决条件是需要 Vue.use(Vuex) 之后执行,因此在 main.js 中直接引入使用Vuex 和 store配置项时,就会出现报错

例如,如下main.js代码,便会出现报错

// 错误示范案例

// 引入Vue
import Vue from "vue";
// 引入App
import App from "./App.vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);
// 引入store配置项
import store from "./store";

Vue.config.productionTip = false;

// 创建vm
new Vue({
  el: "#app",
  render: (h) => h(App),
  store,
  // 安装全局事件总线
  beforeCreate() {
    Vue.prototype.$bus = this;
  },
});

由图示可看出错误提示信息,vuex 在创建 store实例 之前必须先调用 Vue.use(Vuex)

四、案例练习 - 求和案例

4.1 Count.vue 

Count子组件:包含4个按钮的点击事件

<template>
  <div style="padding: 20px">
    <h1>当前求和为:{{ $store.state.sum }}</h1>
    <select v-model="n">
      <option :value="1">1</option>
      <option :value="2">2</option>
      <option :value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数再加</button>
    <button @click="incrementWait">等1s后再加</button>
  </div>
</template>

<script>
export default {
  name: "Count",
  data() {
    return {
      n: 1, // 用户选择的数字
    };
  },
  methods: {
    increment() {
      this.$store.commit("ADD", this.n);
    },
    decrement() {
      this.$store.commit("SUB", this.n);
    },
    incrementOdd() {
      this.$store.dispatch("addOdd", this.n);
    },
    incrementWait() {
      this.$store.dispatch("addWait", this.n);
    },
  },
};
</script>

<style></style>

4.2 App.vue

引入Count组件作为子组件,并使用Count组件标签

<template>
    <div>
      <Count></Count>
    </div>
</template>

<script>
import Count from "./components/Count.vue";
export default {
  name: "App",
  components: { Count },
};
</script>

<style></style>

4.3 index.js

store配置,准备了actions、mutations、state

// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);

// 准备actions对象 - 响应组件中用户的动作
const actions = {
  add(context, value) {
    context.commit("ADD", value);
  },
  sub(context, value) {
    context.commit("SUB", value);
  },
  addOdd(context, value) {
    if (context.state.sum % 2) {
      context.commit("ADD", value);
    }
  },
  addWait(context, value) {
    setTimeout(() => {
      context.commit("ADD", value);
    }, 1000);
  },
};
// 准备mutations对象 - 修改state中的数据
const mutations = {
  ADD(state, value) {
    state.sum += value;
  },
  SUB(state, value) {
    state.sum -= value;
  },
};
// 准备state对象 - 保存具体数据
const state = {
  sum: 0,
};

// 创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
});

Logo

前往低代码交流专区

更多推荐