Skip to content

通过createStore创建一个store实例

js
import { createApp } from "vue";
import { createStore } from "vuex";

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

const app = createApp({
    /* 根组件 */
});

// 将 store 实例作为插件安装
app.use(store);
import { createApp } from "vue";
import { createStore } from "vuex";

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

const app = createApp({
    /* 根组件 */
});

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

核心概念

state

在 Vue 组件中,可以使用this.$store访问store实例,访问状态使用this.$store.state.count

原理是 app.use(store)的时候,将 store 实例挂在到 Vue 原型上,重命名为$store,因此每个 Vue 组件实例都可以访问 store 实例

可以使用 mapState 辅助函数来进行映射

js
import { mapState } from 'vuex'

export default {
    computed: {
        ...mapState({
            // 箭头函数可使代码更简练
            count: state => state.count,

            // 传字符串参数 'count' 等同于 `state => state.count`
            countAlias: 'count',

            // 为了能够使用 `this` 获取局部状态,必须使用常规函数
            countPlusLocalState (state) {
            return state.count + this.localCount
        })
    }
}
import { mapState } from 'vuex'

export default {
    computed: {
        ...mapState({
            // 箭头函数可使代码更简练
            count: state => state.count,

            // 传字符串参数 'count' 等同于 `state => state.count`
            countAlias: 'count',

            // 为了能够使用 `this` 获取局部状态,必须使用常规函数
            countPlusLocalState (state) {
            return state.count + this.localCount
        })
    }
}

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

js
computed: mapState([
    // 映射 this.count 为 store.state.count
    "count",
]);
computed: mapState([
    // 映射 this.count 为 store.state.count
    "count",
]);

Getter

Getter 相当于 state 的计算属性,会添加到响应式缓存中。

定义 Getters

js
getters: {
  // ...
  doneTodosCount (state, getters) {
    return getters.doneTodos.length
  }
}
getters: {
  // ...
  doneTodosCount (state, getters) {
    return getters.doneTodos.length
  }
}

获取 Getters

  1. 通过属性访问

在 Vue 组件中可以通过,this.$store.getters.doneTodos来访问

  1. 通过方法访问
  2. mapGetters

Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,使用this.$store.commit('increment', 10)来提交 mutation

mutation 必须是同步函数,目的是只有是同步函数,devtools 才能跟踪到状态的改变。所以这里使用异步也是可以执行的,可能会有警告,但不是绝对禁止。

action

Action 类似于 mutation,二者几乎一模一样,不同在于:

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

action 采用 dispatch 来派发,this.$store.dispatch('increment')

项目结构

需要遵守的规则:

  1. 应用层级的状态应该集中到单个 store 对象中。

  2. 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。

  3. 异步逻辑都应该封装到 action 里面。

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

bash
├── index.html
├── main.js
├── api
   └── ... # 抽取出API请求
├── components
   ├── App.vue
   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块
├── index.html
├── main.js
├── api
   └── ... # 抽取出API请求
├── components
   ├── App.vue
   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

组合式 API

可以通过调用 useStore 函数,来在 setup 钩子函数中访问 store。这与在组件中使用选项式 API 访问 this.$store 是等效的。

js
import { useStore } from "vuex";

export default {
    setup() {
        const store = useStore();
    },
};
import { useStore } from "vuex";

export default {
    setup() {
        const store = useStore();
    },
};

访问 State 和 Getter

js
import { computed } from "vue";
import { useStore } from "vuex";

export default {
    setup() {
        const store = useStore();

        return {
            // 在 computed 函数中访问 state
            count: computed(() => store.state.count),

            // 在 computed 函数中访问 getter
            double: computed(() => store.getters.double),
        };
    },
};
import { computed } from "vue";
import { useStore } from "vuex";

export default {
    setup() {
        const store = useStore();

        return {
            // 在 computed 函数中访问 state
            count: computed(() => store.state.count),

            // 在 computed 函数中访问 getter
            double: computed(() => store.getters.double),
        };
    },
};

访问 Mutation 和 Action

js
import { useStore } from "vuex";

export default {
    setup() {
        const store = useStore();

        return {
            // 使用 mutation
            increment: () => store.commit("increment"),

            // 使用 action
            asyncIncrement: () => store.dispatch("asyncIncrement"),
        };
    },
};
import { useStore } from "vuex";

export default {
    setup() {
        const store = useStore();

        return {
            // 使用 mutation
            increment: () => store.commit("increment"),

            // 使用 action
            asyncIncrement: () => store.dispatch("asyncIncrement"),
        };
    },
};