Vuex(Vue的状态管理模式)总结

Vuex

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

简单地说:对vue应用中多个组件的共享状态进行集中式的管理(读/写)

安装

npm install vuex
yarn add vuex

在一个模块化的打包系统中,必须显式地通过 Vue.use() 来安装 Vuex:

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

Vue.use(Vuex)

store(仓库)

Vuex应用的核心是就是store,“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)Vuex和单纯的全局对象有以下两点不同:

1.Vuex 的状态存储是响应式的。当Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

创建

// store对象中包含读取数据和更新数据的方法
const store = new Vuex.Store({
  state,
  actions,
  mutations,
});
// 暴露出去
export default store;

为了在 Vue 组件中访问 this.$store property,需要为 Vue实例提供创建好的 store。

import store from "./store";
new Vue({
  render: (h) => h(App),
  // 应用store
  store,
}).$mount("#app");

State

单一状态树

Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。作为一个“唯一数据源 ”而存在.

这也意味着,每个应用将仅仅包含一个 store 实例。

const state = {
  // 数据的初始化
  count: 0,
};

Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数.在 Vuex 中,也可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)

const mutations = {
  // mutation函数第一个参数:state --> 所有状态数据
  // mutation函数第二个参数:num --> 就由上一步actions负责传递过来
  INCREMENT(state, num) {
    state.count += num;
  },
  DECREMENT(state, num) {
    state.count -= num;
  },
};

Mutation 需遵守 Vue的响应规则

既然Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用Vue 一样遵守一些注意事项:

  1. 最好提前在你的 store 中初始化好所有所需属性。
  2. 当需要在对象上添加新属性时,你应该
  • 使用 Vue.set(obj, 'newProp', 123), 或者
  • 以新对象替换老对象。例如,利用[对象展开运算符 我们可以这样写:
state.obj = { ...state.obj, newProp: 123 }

Actions

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

注册一个action:

const actions = {
    // actions函数第一个参数是一个对象:store --> 内部有dispatch/commit/state等
    // actions函数第二个参数:组件中分发dispatch传递过来的数据
    increment(store, num) {
        console.log(store, num);
        // 触发某一个mutation函数
        // store.commit(触发的mutation函数名称, mutation函数要接受的数据);
        store.commit("INCREMENT", num);
    },
    incrementAsync({ commit }, num) {
        setTimeout(() => {
            commit("INCREMENT", num);
        }, 1000)
    },
    isType({ commit, state: { count } }) {
        if (count % 2 === 1) {
            commit("ISTYPEODD");
            return
        }
        commit("ISTYPEEVEN")
    }

};

分发Action

组件中Action 通过 this.$store.dispatch方法触发:

 methods: {
    increment() {
      // 更新vuex数据 --> dispatch 调用store中的actions 并传递数据
      this.$store.dispatch("increment", this.num);
      this.$store.dispatch("isType");
    },
    decrement() {
      this.$store.dispatch("decrement", this.num);
      this.$store.dispatch("isType");
    },
    incrementAsync() {
      this.$store.dispatch("incrementAsync", this.num);
      setTimeout(() => { // 可以异步调用
        this.$store.dispatch("isType");
      }, 1000);
    },
  }

Actions 支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

getters

Vuex可以在store中定义getters(可以认为是 store 的计算属性).

Getter 接受 state 作为其第一个参数:

const getters = {
    oddOrEven(state) {
        // Math.abs() 取绝对值(正数)
        return Math.abs(state.count) % 2 === 1 ? "奇数" : "偶数";
    }
}

Getter 会暴露为 store.getters 对象,可以以属性的形式访问这些值:

store.getters.xxx

辅助函数

/*
  mapState 映射vuex状态数据到组件data数据中 计算属性computed中
  mapGetters 映射vuex的store中的 getters数据到组件computed数据中
  mapActions 映射vuex actions函数到组件methods中
  mapMutations 映射vuex mutations函数到组件methods中
*/

导入

import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
computed: {
    /* 
        mapState(["count"]) 的返回值是一个对象
        {
            count(){
                return this.$store.state.count
            }
        }
      */
    ...mapState(["count"]),
    ...mapGetters(["oddOrEven"])
  },
 methods: {
    ...mapActions(["incrementIfOdd", "incrementAsync"]),
    ...mapMutations([INCREMENT, DECREMENT]),
    increment() {
      //this.$store.commit("INCREMENT", this.num);
      // 调用的就是mutation函数
      this.INCREMENT(this.num);
    },
    incrementIfOdd() {
      //this.$store.dispatch("incrementIfOdd", this.num);
      this.INCREMENT(this.num)
    },
  }

vuex 工作流程

  • 读取

    • 组件直接调用 this.$store.state.xxx
      • mapState([‘count’])
    • 组件直接调用 this.$store.getters.xxx
      • mapGetters([‘oddOrEven’])
  • 更新

    • 组件调用 this.$store.dispatch(‘action 函数名称’, 数据)

      • mapActions([‘increment’])
    • 触发某个 actions 函数,actions 函数中发送请求,请求成功调用 commit(‘mutation 函数名称’, 数据)

    • 触发某个 mutations 函数,mutations 函数就会对 state 数据进行直接修改

    • 数据一旦更新,因为响应式的原因,所以用户界面也会发生变化

    • 组件调用 this.$store.commit(‘mutation 函数名称’, 数据)

      • mapMutations([‘INCREMENT’])
    • 触发某个 mutations 函数,mutations 函数就会对 state 数据进行直接修改

    • 数据一旦更新,因为响应式的原因,所以用户界面也会发生变化

思考:

  • 状态数据要不要定义在 vuex 中?
    • 看数据是否有多个组件要使用(显示、操作)
  • 要对 vuex 的数据进行操作,要不要 actions?
    • 要数据需不需要进一步处理(操作:发送请求…)
  • mutation 函数要定义多少个?
    • 看要对数据进行几种类型的操作
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页