调用API
// require.context 动态加载模块文件夹下的所有 .js 文件
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// 通过正则表达式提取每个模块文件的名称,并将这些模块加载到一个对象中
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
export default {
// 将所有加载的模块挂载到 Vue 应用实例的全局属性 $api 上
install(app){
app.config.globalProperties.$api = modules;
}
}
好处:
- 动态加载:可以自动加载指定目录下的所有模块,无需手动导入每一个模块。
- 简化调用:在 Vue 组件内部可以直接通过 this.$api 访问到所有的 API 方法,提高了开发效率。
主应用文件 main.js
import { createApp } from 'vue'
import App from './App.vue'
import api from './api'
const app = createApp(App)
api.install(app)
// api.use(app)
app.mount('#app')
现在在任何 Vue 组件中,都可以直接使用 API 方法:
methods: {
async fetchData() {
const homeData = await this.$api.app.fetchHomeData()
const userInfo = await this.$api.user.fetchUserInfo(1)
// ...
}
}
在 Vue 中,api.install(app) 和 api.use(app) 都是用来将自定义的功能或插件集成到 Vue 应用中的方法。虽然这两个方法在功能上非常相似,但在不同的库或框架中可能会有所不同。下面分别解释这两种用法:
- api.install(app)
用途: install 方法通常用于 Vue 插件的安装。它接收一个 Vue 应用实例作为参数,并将插件的功能添加到该应用实例上。
示例: 在你的代码中,api.install(app) 将所有 API 方法注册到了 Vue 应用实例的全局属性 $api 上,使得这些 API 方法可以在任何
V
u
e
组件
Vue 组件
Vue组件中通过 this.$api 访问。
- api.use(app)
用途: use 方法也是用于将插件或功能集成到 Vue 应用中的。它同样接收一个 Vue 应用实例作为参数,并执行相应的初始化操作。
示例: 虽然你的代码中没有使用 api.use(app),但在其他情况下,如果一个插件或库提供了 use 方法,那么它可能是用来完成类似的任务——将插件的功能集成到 Vue 应用中。
- 总结
相同点:
install 和 use 都是用来将插件或功能集成到 Vue 应用中的方法。
不同点:
install 方法更常见于 Vue 的官方文档和社区实践中,用于插件的安装。
use 方法在某些第三方库中可能会使用,但不是 Vue 官方推荐的标准命名。
登录
login() {
// this.$refs["loginForm"].validate() 方法 验证登录表单是否有效
this.$refs["loginForm"].validate((valid) => {
if (valid) {
// 设置加载状态:如果表单验证通过,则设置 this.loginLoading 为 true,表示正在进行登录操作。
this.loginLoading = true;
// 发起登录请求: 使用 $api["system/auth"].login(this.loginForm) 发起登录请求,其中 this.loginForm 是包含登录信息的对象(如用户名和密码)。
this.$api["system/auth"].login(this.loginForm).then((res) => {
// 处理响应
// 成功响应时:
// 从响应数据中获取 token,并调用 setToken 函数存储 token。
setToken(res.data.token);
// 调用 this.setUser 和 this.setNetwork 方法来更新用户信息和网络信息。
this.setUser(res.data.user);
this.setNetwork(res.data.user.network);
this.$router.push("/home")
// 显示一条消息提示,类型根据登录结果确定。
ElMessage({
type: res.data.msg === "login success" ? "success":"warning",
message: res.data.msg,
});
})
// 不管成功还是失败,最后都会调用 .finally() 方法来重置 this.loginLoading 为 false,表示登录操作已完成。
.finally(() => {
this.loginLoading = false;
});
}
});
},
mapActions
mapActions 是 Vuex 提供的一个辅助函数,用于将 store 中定义的 actions 映射到组件的 methods 中,使得组件可以直接调用这些 actions 而不需要通过 this.$store.dispatch
- 假设有以下 Vuex store 的结构:
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
user: {
namespaced: true,
actions: {
aSetUser(context, payload) {
// 更新用户信息
context.commit('mSetUser', payload)
}
}
},
network: {
namespaced: true,
actions: {
setNetwork(context, payload) {
// 更新网络信息
context.commit('mSetNetwork', payload)
}
}
}
}
})
- 在 Vue 组件中,可以这样使用这些映射的 actions:
<template>
<div>
<button @click="setUser">Set User</button>
<button @click="setNetwork">Set Network</button>
</div>
</template>
<script>
export default {
methods: {
...mapActions({
setUser: "user/aSetUser",
setNetwork: "network/setNetwork",
}),
setUser() {
this.setUser({ name: 'John Doe', age: 30 });
},
setNetwork() {
this.setNetwork('5G');
}
}
}
</script>
Vuex
- Actions 是 Vuex 中用于处理异步操作的部分。
- Mutations 用于直接改变状态,而 actions 通过提交 mutations 来间接改变状态。
- Namespaces 可以帮助组织和隔离 actions。
- Dispatch 用于触发 actions。
- mapActions 辅助函数可以简化 actions 的调用。
- Actions 的作用
- 异步操作: Actions 可以包含任何异步操作,如 AJAX 请求、定时器等。
- 提交 Mutations: Actions 通过提交 mutations 来改变状态,而不是直接修改状态。
- Context: Actions 接受一个与 store 实例具有相同方法和属性的 context 对象作为第一个参数,通常可以通过 context.commit 来提交 mutations。
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
// incrementAsync 是一个 action,它会在一秒后提交一个 increment mutation。
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
}
});
- Namespace
当 Vuex store 被组织成模块时,可以使用命名空间来隔离 actions
// store.js
// aSetUser 和 setNetwork 分别属于 user 和 network 模块
// 并且由于设置了 namespaced: true,所以它们的调用需要加上模块的前缀。
export default new Vuex.Store({
modules: {
user: {
namespaced: true,
actions: {
aSetUser(context, payload) {
// 更新用户信息
context.commit('mSetUser', payload);
}
}
},
network: {
namespaced: true,
actions: {
setNetwork(context, payload) {
// 更新网络信息
context.commit('mSetNetwork', payload);
}
}
}
}
});
- this.$store.dispatch
在 Vue 组件中,可以通过 this.$store.dispatch 方法来触发 actions。
methods: {
incrementAsync() {
this.$store.dispatch('incrementAsync');
},
setUser() {
this.$store.dispatch('user/aSetUser', { name: 'John Doe', age: 30 });
},
setNetwork() {
this.$store.dispatch('network/setNetwork', '5G');
}
}
- mapActions
使用 mapActions 辅助函数来简化调用
methods: {
...mapActions([
'incrementAsync',
'user/aSetUser',
'network/setNetwork'
]),
incrementAsync() {
this.incrementAsync();
},
setUser() {
this.aSetUser({ name: 'John Doe', age: 30 });
},
setNetwork() {
this.setNetwork('5G');
}
}