Appearance
通过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
- 通过属性访问
在 Vue 组件中可以通过,this.$store.getters.doneTodos来访问
- 通过方法访问
- 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')
项目结构
需要遵守的规则:
应用层级的状态应该集中到单个 store 对象中。
提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
异步逻辑都应该封装到 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"),
};
},
};