Vue 开发中,Vuex是状态管理的核心工具(统一管理全局数据),而打包发布是项目上线的关键步骤。
一、Vuex:Vue 的全局状态管理工具
当多个组件需要共享数据(如用户信息、购物车)时,Vuex 可以统一管理这些 "全局状态",避免组件间频繁通信。
1. Vuex 核心概念(5 大模块)
Vuex 的核心由State、Getter、Mutation、Action、Module组成(本文先讲前 4 个基础模块):
(1)State:存储全局状态
State是 Vuex 的 "数据仓库",用于存储全局共享的数据。
示例:
javascript
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
// 全局状态
state: {
userInfo: null, // 用户信息
cartCount: 0 // 购物车数量
}
});
组件中使用 State:
vue
<!-- 方式1:直接通过$store访问 -->
<div>{{ $store.state.cartCount }}</div>
<!-- 方式2:通过mapState辅助函数(更简洁) -->
<div> {{ cartCount }} </div>
<div> {{ userInfo }} </div>
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['cartCount', 'userInfo'])
}
};
</script>
(2)Getter:对 State 的计算属性
Getter类似 Vue 的computed,用于对State进行计算、过滤(结果会缓存)。
示例:
javascript
// src/store/index.js
export default new Vuex.Store({
state: {
cartList: [
{ id: 1, name: '苹果', count: 2 },
{ id: 2, name: '香蕉', count: 3 }
]
},
// Getter:计算购物车总数量
getters: {
totalCartCount(state) {
return state.cartList.reduce((sum, item) => sum + item.count, 0);
}
}
});
组件中使用 Getter:
vue
<!-- 方式1:直接通过$store访问 -->
<template>
<div>购物车总数:{{ $store.getters.totalCartCount }}</div>
</template>
----------------------
<!-- 方式2:通过mapGetters辅助函数(更简洁) -->
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters(['totalCartCount'])
}
};
</script>
<template>
<div>购物车总数:{{ totalCartCount }}</div>
</template>
(3)Mutation:修改 State 的唯一方式
Mutation是同步修改State 的唯一入口(必须是同步函数),用于保证状态变更可追踪。
示例:
javascript
// src/store/index.js
export default new Vuex.Store({
state: { cartCount: 0 },
// Mutation:定义修改规则
mutations: {
// 增加购物车数量
INCREMENT_CART(state, payload) {
state.cartCount += payload;
},
// 设置用户信息
SET_USER_INFO(state, userInfo) {
state.userInfo = userInfo;
}
}
});
组件中触发 Mutation:
vue
<script>
import { mapMutations } from 'vuex';
export default {
methods: {
...mapMutations(['INCREMENT_CART']),
addCart() {
// 方式1:通过mapMutations触发
this.INCREMENT_CART(1);
// 方式2:直接通过$store.commit触发
// this.$store.commit('INCREMENT_CART', 1);
}
}
};
</script>
(4)Action:处理异步操作
Action用于处理异步逻辑(如接口请求),最终通过触发Mutation修改 State。
示例:
javascript
// src/store/index.js
import { login } from '@/api/user'; // 假设已封装登录接口
export default new Vuex.Store({
mutations: {
SET_USER_INFO(state, userInfo) {
state.userInfo = userInfo;
}
},
// Action:处理异步请求
actions: {
async loginAction({ commit }, form) {
const res = await login(form); // 异步请求
commit('SET_USER_INFO', res.userInfo); // 触发Mutation修改State
return res; // 返回结果给组件
}
}
});
组件中触发 Action:
vue
<script>
import { mapActions } from 'vuex';
export default {
methods: {
// 方式1:通过mapActions辅助函数(简化写法)
...mapActions(['loginAction']),
async onLoginByMap() {
const res = await this.loginAction(this.form);
console.log('登录成功', res);
},
// 方式2:原生$store.dispatch调用(更直观)
async onLoginByDispatch() {
// dispatch 和 commit 用法一样, 区别就是 commit 调用的是 mutations 的函数, dispatch 调用的是 actions 的函数
const res = await this.$store.dispatch('loginAction', this.form);
console.log('登录成功', res);
}
}
};
</script>
二、项目打包发布:核心配置
项目开发完成后,需要打包为静态资源部署到服务器,关键配置包括publicPath和 "路由懒加载"。
1. 配置 publicPath:解决资源路径问题
publicPath用于指定项目部署的基础路径(如部署在子目录/my-app/下),避免打包后资源路径错误。
配置方式:
在vue.config.js中添加:
javascript
// vue.config.js
module.exports = {
// 若部署在根目录,设为'/';若部署在子目录,设为'/子目录名/'
publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/'
};
2. 路由懒加载:优化打包体积
默认打包会将所有页面代码打包到一个文件中,体积较大。路由懒加载可以将页面拆分为多个小文件,按需加载。
配置方式:
在router/index.js中,将组件导入改为动态导入:
javascript
// 原写法:全部打包到一个文件
// import Home from '@/views/Home.vue';
// 懒加载写法:拆分多个文件
const Home = () => import('@/views/Home.vue');
const Login = () => import('@/views/Login.vue');
const routes = [
{ path: '/', component: Home },
{ path: '/login', component: Login }
];
效果:打包后会生成多个chunk文件,访问对应页面时才加载对应的代码,提升首屏加载速度。