项目文件:
TypeNav.vue(导航栏组件,在整体home组件中的一部分)
<script>
import { mapState } from 'vuex';
export default {
name:"TypeNav",
mounted(){
this.$store.dispatch('categoryList')
},
computed:{
...mapState({
categoryList:(state)=>{
return state.home.categoryList;
}
})
}
}
</script>
home页面模块中是包含typenav组件的,home组件被单独分为vuex中的一个moudle,其中/store/home/index.js代码如下
import { reqCategoryList } from "@/api/getBase";
//state:仓库存储数据的地方
const state ={
categoryList:[]
};
//mutations:修改state的唯一手段
const mutations ={
CATEGORYLIST(state,categoryList){
state.categoryList = categoryList
}
};
//action:处理action,可以书写自己的业务逻辑,也可以处理异步
const actions={
// 通过API里面的接口函数调用,向服务器发送请求,获取服务器数据
async categoryList({commit}){
const result = await reqCategoryList()
// console.log("111",result)
if (result.code ==200){
commit("CATEGORYLIST",result.data)
}
}
};
//getters:理解为计算属性,用于简化仓库数据,让组件获取仓库的数据更加方便const getters ={};
const getters={};
//创建并暴露store
export default ({
state,
getters,
mutations,
actions,
})
梳理整个流程的逻辑关系,用清晰的步骤和命名对照说明:
1. 组件与Vuex模块的命名对照表
位置 | 命名 | 作用 |
---|---|---|
组件文件 | TypeNav.vue | 导航栏组件,负责展示商品分类列表 |
Vuex模块名 | home | 首页相关的状态管理模块(独立模块) |
Vuex状态(state) | categoryList | 存储商品分类列表数据(初始为空数组) |
Vuex动作(action) | categoryList | 异步请求分类数据,提交给mutation更新状态 |
Vuex突变(mutation) | CATEGORYLIST | 唯一能修改categoryList 状态的方法(全大写是Vuex命名惯例) |
2. 数据流完整流程
步骤1:组件挂载时触发Action
// TypeNav.vue
mounted() {
this.$store.dispatch('categoryList') // 触发名为'categoryList'的action
}
步骤2:Action调用API并提交Mutation
// home模块的actions
async categoryList({ commit }) {
const result = await reqCategoryList() // 调用接口函数
if (result.code == 200) {
commit("CATEGORYLIST", result.data) // 提交mutation更新state
}
}
步骤3:Mutation修改State
// home模块的mutations
CATEGORYLIST(state, categoryList) {
state.categoryList = categoryList // 直接修改状态
}
步骤4:组件通过mapState获取数据
// TypeNav.vue
computed: {
...mapState({
categoryList: (state) => state.home.categoryList // 映射state到计算属性
})
}
步骤5:模板渲染
<!-- TypeNav.vue的template -->
<!-- 可通过categoryList使用数据,例如v-for循环 -->
<div v-for="category in categoryList" :key="category.id">
{{ category.name }}
</div>
3. 关键命名为什么这样设计?
-
Action命名
categoryList
- 与API方法同名(
reqCategoryList
),表示"获取分类列表"的动作。 - 使用小驼峰(Vuex推荐action用小写或驼峰)。
- 与API方法同名(
-
Mutation命名
CATEGORYLIST
- 全大写是Vuex惯例(类似常量,表示这是同步状态修改)。
- 对应action的逻辑(action处理异步,mutation执行实际修改)。
-
State命名
categoryList
- 直接描述存储的内容类型(分类列表数组)。
- 与API返回的数据结构一致。
4. 可能混淆的点澄清
Q1: 为什么categoryList
在三个地方重复出现?
- Action:
categoryList
是函数名(发起异步请求)。 - Mutation:
CATEGORYLIST
是修改状态的方法名。 - State:
categoryList
是存储的数据字段名。
它们职责不同,通过命名大小写区分。
Q2: mapState
中的state.home
是哪来的?
home
是Vuex模块名,在注册store时指定:// store/index.js modules: { home: homeModule // 模块名home对应home模块的状态 }
- 因此需要通过
state.home
访问该模块的状态。
5. 完整调用链图示
TypeNav组件 mounted()
→ dispatch('categoryList')
→ home模块的actions.categoryList()
→ 调用API reqCategoryList()
→ 成功则commit('CATEGORYLIST', data)
→ home模块的mutations.CATEGORYLIST()
→ 修改state.categoryList
→ 通过mapState自动更新组件计算属性
→ 触发模板重新渲染
6. 改进建议(可选)
如果觉得命名重复易混淆,可以这样调整:
// 修改action和mutation名称(保持语义清晰)
actions: {
async fetchCategoryList({ commit }) { /*...*/ }
},
mutations: {
SET_CATEGORY_LIST(state, data) { /*...*/ }
}
但原有命名符合Vuex惯例,保持一致性更重要。理解后就不会混淆了。