Skip to content

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。

https://vuex.vuejs.org/zh/index.html

vite创建一个项目

shell
npm init vite@latest my-vuex -- --template vue
cd my-vuex
cnpm install

安装

shell
cnpm install vuex@next --save

state

state -> 存放数据

src/store/index.js

js
import { createStore } from "vuex";

// 创建一个新的 store 实例
const store = createStore({
  state() {
    return {
      count: 0,
    };
  },
});

export default store;

main.js

js
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);

// 将 store 实例作为插件安装
app.use(store);

app.mount("#app");
vue
<template>
  <h1>{{ $store.state.count }}</h1>
  <!-- 不建议这样操作数据 -->
  <!-- <button @click="$store.state.count++">click</button> -->
</template>

mutation -> 同步修改数据

js
import { createStore } from "vuex";

// 创建一个新的 store 实例
const store = createStore({
    state() {
        return {
            count: 0,
        };
    },
    mutations: {
        increment(state, value) {
            if (value) {
                console.log(value);
                state.count += value;
            } else {
                state.count++;
            }
        },
    },
});

export default store;
vue
<template>
  <h1>{{ $store.state.count }}</h1>
  <button @click="increment">click</button>
  <button @click="increment2(5)">add 5</button>
</template>
<script>
export default {
  methods: {
    increment() {
      // 提交一个变更
      this.$store.commit("increment");
    },
    increment2(num) {
      // 传值
      this.$store.commit("increment", num);
    },
  },
};
</script>

getter

src/store/index.js

js
import { createStore } from "vuex";

// 创建一个新的 store 实例
const store = createStore({
    state() {
        return {
            count: 0,
            msg: "hello",
        };
    },
    // 可以认为是 store 的计算属性
    getters: {
        reverMsg(state) {
            return state.msg.split("").reverse().join("");
        },
        // 第二个参数可以拿到getters中的函数
        reverMsgLength(state, getters) {
            return getters.reverMsg.length;
        },
    },
    mutations: {
        increment(state, value) {
            if (value) {
                console.log(value);
                state.count += value;
            } else {
                state.count++;
            }
        },
    },
});

export default store;
vue
<template>
  <h1>{{ $store.state.count }}</h1>
  <button @click="increment">click</button>
  <button @click="increment2(5)">add 5</button>

  <h1>{{ $store.getters.reverMsg }}</h1>
  <h1>{{ $store.getters.reverMsgLength }}</h1>
</template>
<script>
export default {
  methods: {
    increment() {
      // 提交一个变更
      this.$store.commit("increment");
    },
    increment2(num) {
      // 传值
      this.$store.commit("increment", num);
    },
  },
};
</script>

action

Action 类似于 mutation,不同在于:

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

src/store/index.js

js
import { createStore } from "vuex";

// 创建一个新的 store 实例
const store = createStore({
  // 存放数据
  state() {
    return {
      count: 0,
      msg: "hello",
    };
  },
  // 可以认为是 store 的计算属性
  getters: {
    reverMsg(state) {
      return state.msg.split("").reverse().join("");
    },
    // 第二个参数可以拿到getters中的函数
    reverMsgLength(state, getters) {
      return getters.reverMsg.length;
    },
  },
  // 同步变更数据
  mutations: {
    increment(state, value) {
      if (value) {
        console.log(value);
        state.count += value;
      } else {
        state.count++;
      }
    },
    updateMsg(state, value) {
      state.msg = value;
    },
  },
  // 和后台交互获取数据
  actions: {
    // context: 一个与store实例具有相同方法和属性的对象
    getData(context, params) {
      console.log(context);
      console.log(params);
      fetch("http://localhost/web/api/demo/test/time")
        .then((res) => {
          return res.json();
        })
        .then((res) => {
          console.log(res);
          context.commit("updateMsg", res.data);
        });
    },
  },
});

export default store;
vue
<template>
  <h1>{{ $store.state.count }}</h1>
  <button @click="increment">click</button>
  <button @click="increment2(5)">add 5</button>

  <h1>{{ $store.getters.reverMsg }}</h1>
  <h1>{{ $store.getters.reverMsgLength }}</h1>

  <button @click="getData">getData</button>
</template>
<script>
export default {
  methods: {
    increment() {
      // 提交一个变更
      this.$store.commit("increment");
    },
    increment2(num) {
      // 传值
      this.$store.commit("increment", num);
    },
    getData() {
      this.$store.dispatch("getData", "666");
    },
  },
};
</script>

辅助函数

mapState, mapMutations, mapGetters, mapActions

vue
<template>
  <h2>{{ getNum }}</h2>
  <h2>{{ count }}</h2>
  <h2>{{ msg }}</h2>
  <h2>{{ reverMsg }}</h2>

  <button @click="addNum">{{ count }}</button>
</template>
<script>
import { mapState, mapMutations, mapGetters, mapActions } from "vuex";
export default {
  data() {
    return {
      num: 2,
    };
  },
  //   computed: mapState({
  //     // count: (state) => state.count
  //     count: "count",
  //   }),
  // computed: mapState(["count", "msg"]),
  // 与局部计算属性混合使用
  computed: {
    getNum() {
      return this.num * 2;
    },
    addNum() {
      this.increment(10);
    },
    ...mapState(["count", "msg"]),
    ...mapGetters(["reverMsg"]),
  },
  methods: {
    ...mapMutations(["increment"]),
    ...mapActions(["getData"]),
  },
  mounted() {
    this.getData();
    console.log(this.count);
    console.log(this.msg);
  },
};
</script>
js
import { createStore } from "vuex";
import user from "./user";

// 创建一个新的 store 实例
const store = createStore({
  modules: {
    a: user,
  },
  // 存放数据
  state() {
    return {
      count: 0,
      msg: "hello",
    };
  },
  // 可以认为是 store 的计算属性
  getters: {
    reverMsg(state) {
      return state.msg.split("").reverse().join("");
    },
    // 第二个参数可以拿到getters中的函数
    reverMsgLength(state, getters) {
      return getters.reverMsg.length;
    },
  },
  // 同步变更数据
  mutations: {
    increment(state, value) {
      if (value) {
        console.log(value);
        state.count += value;
      } else {
        state.count++;
      }
    },
    updateMsg(state, value) {
      state.msg = value;
    },
  },
  // 和后台交互获取数据
  actions: {
    // context: 一个与store实例具有相同方法和属性的对象
    getData(context, params) {
      console.log(context);
      console.log(params);
      fetch("http://localhost/web/api/demo/test/time")
        .then((res) => {
          return res.json();
        })
        .then((res) => {
          console.log(res);
          context.commit("updateMsg", res.data);
        });
    },
  },
});

export default store;

module

将 store 分割成模块(module)。 每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

js
const user = {
    state: () => ({
        name: "Patrick",
    }),
    getters: {
        // rootState: 根节点状态
        getName(state, getters, rootState) {
            console.log(getters);
            console.log(rootState);
            return state.name + "666";
        },
    },
};

export default user;
js
import { createStore } from "vuex";
import user from "./user";

// 创建一个新的 store 实例
const store = createStore({
  modules: {
    a: user,
  },
  // 存放数据
  state() {
    return {
      count: 0,
      msg: "hello",
    };
  },
  // 可以认为是 store 的计算属性
  getters: {
    reverMsg(state) {
      return state.msg.split("").reverse().join("");
    },
    // 第二个参数可以拿到getters中的函数
    reverMsgLength(state, getters) {
      return getters.reverMsg.length;
    },
  },
  // 同步变更数据
  mutations: {
    increment(state, value) {
      if (value) {
        console.log(value);
        state.count += value;
      } else {
        state.count++;
      }
    },
    updateMsg(state, value) {
      state.msg = value;
    },
  },
  // 和后台交互获取数据
  actions: {
    // context: 一个与store实例具有相同方法和属性的对象
    getData(context, params) {
      console.log(context);
      console.log(params);
      fetch("http://localhost/web/api/demo/test/time")
        .then((res) => {
          return res.json();
        })
        .then((res) => {
          console.log(res);
          context.commit("updateMsg", res.data);
        });
    },
  },
});

export default store;
vue
<template>
  <h1>{{ $store.state.count }}</h1>
  <button @click="increment">click</button>
  <button @click="increment2(5)">add 5</button>

  <h1>{{ $store.getters.reverMsg }}</h1>
  <h1>{{ $store.getters.reverMsgLength }}</h1>

  <button @click="getData">getData</button>

  <hr />

  <h1>{{ $store.getters.getName }}</h1>
  <h1>{{ $store.state.a.name }}</h1>
</template>
<script>
export default {
  methods: {
    increment() {
      // 提交一个变更
      this.$store.commit("increment");
    },
    increment2(num) {
      // 传值
      this.$store.commit("increment", num);
    },
    getData() {
      this.$store.dispatch("getData", "666");
    },
  },
};
</script>

命名空间 namespaced: true

js
const user = {
  namespaced: true,
  state: () => ({
    name: "Patrick",
  }),
  getters: {
    // rootState: 根节点状态
    getName(state, getters, rootState) {
      console.log(rootState);
      console.log(getters);
      return state.name + "666";
    },
  },
};

export default user;
vue
<!-- <h1>{{ $store.getters.getName }}</h1> -->
<h1>{{ $store.getters["a/getName"] }}</h1>