blog icon indicating copy to clipboard operation
blog copied to clipboard

Vuex 使用入门

Open yanyue404 opened this issue 5 years ago • 0 comments

Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

  1. 状态共享,非父子组件通信
  2. 数据快照,缓存数据,避免重复请求,影响用户体验
  3. dev 环境下 time-travel 调试

实现模式

利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新

流程解读

mutation 必须同步执行, Action ,我们则可以在 action 内部执行异步操作:

同步流程:vue component -> commit 触发 mutations 定义的方法 -> store.state -> render

// 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
});

触发 mutations

store.commit("increment");

异步流程: vue component -> dispatch 触发 actions 定义的方法 -> commit 触发 mutations 定义的方法 -> store.state -> render

const store = new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
  actions: {
    increment(context) {
      context.commit("increment");
    },
  },
});

辅助函数

  • mapState
  • mapMutations
  • mapGetter
  • mapActions

实例使用

vuex 注册:

import Vue from "vue";
import Vuex from "vuex";
import createPersistedState from "vuex-persistedstate";
import prdConfig from "../../prd-config";
import mutations from "./mutations";
import actions from "./actions";
import todos from "./modules/todos";

Vue.use(Vuex);
const store = () =>
  new Vuex.Store({
    modules: {
      todos,
    },
    state: {
      env: "dev",
    },
    mutations,
    actions,
    plugins: [
      createPersistedState({
        storage: window.sessionStorage, // 持久化默认使用 localStorage
        key: `vuex_${prdConfig.productCode}`,
      }),
    ],
  });
export default store;

模块化管理使用:

import { getTodoData } from "@/plugins/http/api";
import Vue from "vue";
const todos = {
  namespaced: true,
  state: () => ({
    todos: [],
    filterType: "all",
  }),
  getters: {
    displayTodos({ todos, filterType }, getters, rootState, rootGetters) {
      return todos.filter((v) => v.type === filterType);
    },
    doneTodosCount({ todos }) {
      return todos.filter((v) => v.isCompleted).length;
    },
  },
  mutations: {
    setFilterType(state, val) {
      state.filter = val;
    },
    setTodo(state, obj) {
      state.todos = obj;
    },
    addTodo(state, obj) {
      state.todos = state.todos.concat([obj]);
    },
    clearAllCompleted(state, obj) {
      state.todos = state.todos.filter((v) => !v.isCompleted);
    },
  },
  actions: {
    async initTodo(
      { commit, dispatch, getters, rootState, state },
      payload = {}
    ) {
      try {
        let { code, message, data } = await getTodoData(payload);
        if (code === "0") {
          if (data) {
            commit("setTodo", data);
			// dispatch('otherModule/updateTODO', data, {root: true});
          }
        } else {
          Vue.prototype.$toast({
            text: message,
          });
        }
      } catch (error) {
        console.log(error);
        Vue.prototype.$toast({ text: "查询 todos 失败,请稍后重试..." });
      }
    },
  },
};
export default todos;

组件中使用:

import { mapActions, mapState, mapMutations, mapGetters } from "vuex";
export default {
  name: "TodoList",
  computed: {
    ...mapState({
      todos: (state) => state.todos.todos,
      filterType: (state) => state.todos.filterType,
    }),
    ...mapGetters({
      displayTodos: "todos/displayTodos",
      doneTodosCount: "todos/doneTodosCount",
    }),
  },
  methods: {
    ...mapMutations("todos", ["addTodo", "clearAllCompleted"]),
    ...mapActions("todos", ["initTodo"]),
  },
};

参考

yanyue404 avatar Oct 22 '19 00:10 yanyue404