白日放歌须纵酒,青春作伴好还乡。这篇文章主要讲述实战,Vue 项目中,将 API “类化”相关的知识,希望能为你提供帮助。
前言【类】和【接口】是 javascript 未来的方向,我们的 API 调用也将如此,朝着这个方向和业务模块同步分类、同步升级。本文讲的正是 —— Vue 魔法师,如何将 API “类化”?
万物皆模块,万物可归类。闲言少叙,直接正题。
分类 API
- 环境: Vue2+ 或 Vue3+
vue create vue-api-module
得到如下目录
--src
----store
------index.js
----App.vue
----main.js
然后新建文件 api.js 如下,
--src
----services
------api.js
----store
------index.js
----App.vue
----main.js
基础类 API
我们先创建一个基础类如下:
class BaseApiService
baseUrl = "https://jsonplaceholder.typicode.com";
resource;
constructor(resource)
if (!resource) throw new Error("Resource is not provided");
this.resource = resource;
getUrl(id = "")
return `$this.baseUrl/$this.resource/$id`;
handleErrors(err)
// 处理错误:
console.log( message: "Errors is handled here", err );
- baseUrl:设置请求根路径;
- resource:来源;
- getUrl:获取链接函数,包含 baseUrl、resource、id;
- handleErrors:处理错误函数;
然后,我们再创建一个子类:包含 fetch、get 只读方法。
class ReadOnlyApiService extends BaseApiService
constructor(resource)
super(resource);
async fetch(config = )
try
const response = await fetch(this.getUrl(), config);
return await response.json();
catch (err)
this.handleErrors(err);
async get(id)
try
if (!id) throw Error("Id 不合法");
const response = await fetch(this.getUrl(id));
return await response.json();
catch (err)
this.handleErrors(err);
- fetch:获取数据;
- get:通过 id 获取数据;
接着,我们再创建一个包含可读写方法的子类:post、put、delete
class ModelApiService extends ReadOnlyApiService
constructor(resource)
super(resource);
async post(data = https://www.songbingjia.com/android/)
try
const response = await fetch(this.getUrl(),
method: "POST",
body: JSON.stringify(data)
);
constid= response.json();
return id;
catch (err)
this.handleErrors(err);
async put(id, data = https://www.songbingjia.com/android/)
if (!id) throw Error("Id 不合法");
try
const response = await fetch(this.getUrl(id),
method: "PUT",
body: JSON.stringify(data)
);
constid: responseId= response.json();
return responseId;
catch (err)
this.handleErrors(err);
async delete(id)
if (!id) throw Error("Id 不合法");
try
await fetch(this.getUrl(id),
method: "DELETE"
);
return true;
catch (err)
this.handleErrors(err);
- post:创建数据;
- put:更新数据;
- delete:删除数据;
让我们看看两个简单的继承示例:
class UsersApiService extends ReadOnlyApiService
constructor()
super("users");
class PostsApiService extends ModelApiService
constructor()
super("posts");
【UsersApiService 类】继承了只读类 API —— ReadOnlyApiService,可以使用 fetch、get 两种方法。而 【PostsApiService 类】继承了读写类 API —— ModelApiService,可以使用 fetch、get、post、put、delete 五种方法。
我们也可以根据业务来写继承 API 类:
class AlbumsApiService extends ModelApiService
constructor()
super("albums");
async uploadImage()
/*
这里可以写你的上传图片逻辑
*/
console.log( message: "图片上传成功!" );
return true;
async triggerError()
try
throw Error(" API 模块调用错误!");
catch (err)
this.handleErrors(err);
导出
我们在 api.js 导出这些 API:
export const $api =
users: new UsersApiService(),
posts: new PostsApiService(),
albums: new AlbumsApiService()
;
分类 API 实践在 Vue 项目中如何调用以上的 API 类?我们主要在 Vuex 和 components 中调用它:
storePlugins
- 先创建一个 storePlugins.js:
--src
----plugins
------storePlugins.js
----services
------api.js
----store
------index.js
----App.vue
----main.js
- 在 storePlugins.js 中引入 api.js:
import$apifrom "@/services/api";
export default function(store)
try
store.$api = $api;
catch (e)
console.error(e);
- 在 src/store/index.js 中引入该插件:
...
import storePlugins from "@/plugins/storePlugins";
...
export default new Vuex.Store(
plugins: [storePlugins],
state:
...
);
mixins
- 创建 mixins.js 在如下位置:
--src
----plugins
------mixins.js
------storePlugins.js
----services
------api.js
----store
------index.js
----App.vue
----main.js
- mixin.js:
import Vue from "vue";
import$apifrom "@/services/api";
Vue.mixin(
computed:
$api: () => $api
);
- main.js 全局引入 mixins:
...
import "@/plugins/mixins";
...
调用
OK!现在你就可以在 store 和 components 中调用了,例如:
this.$api.resource.method
------
this.$api.users.fetch()
this.$api.users.get(1)
this.$api.posts.post(post)
this.$api.posts.put(post)
this.$api.posts.delete(1)
this.$api.albums.uploadImage()
this.$api.albums.triggerError()
示例
可本地调试~
- components 中
< template>
< div id="app">
< h1> Vue API “类化” 示例< /h1>
< p> 请打开控制台< /p>
< p> 检查 Vuex store< /p>
< /div>
< /template>
< script>
export default
name: "App",
async created()
// 获取用户资料
await this.$store.dispatch("fetchUsers");
const users = await this.$api.users.fetch();
console.log( message: "Users from the component", users );
// 根据 id 获取用户资料
const user = await this.$api.users.get(1);
console.log( message: "User with id: 1", user );
// 创建新文章
let post =
userId: 1,
title: "测试文章",
body:
"这是一篇测试文章"
;
await this.$store.dispatch("createPost", post);
// 更新文章
post =...post, id: 1 ;
await this.$store.dispatch("updatePost", post);
// 删除文章
await this.$api.posts.delete(post.id);
console.log( message: "成功删除文章!" );
// 执行自定义方法
await this.$api.albums.uploadImage();
// 执行自定义方法
await this.$api.albums.triggerError();
;
< /script>
< style>
#app
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
< /style>
- store 中
import Vue from "vue";
import Vuex from "vuex";
import storePlugins from "@/plugins/storePlugins";
Vue.use(Vuex);
const ADD_USERS = "ADD_USERS";
const ADD_POST = "ADD_POST";
const UPDATE_POST = "UPDATE_POST";
export default new Vuex.Store(
plugins: [storePlugins],
state:
users: [],
posts: []
,
mutations:
[ADD_USERS](state, users)
state.users = users;
,
[ADD_POST](state, post)
state.posts = [...state.posts, post];
,
[UPDATE_POST](state, post)
const index = state.posts.findIndex(( id ) => id === post.id);
if (!~index) state.posts.splice(index, 1, post);
,
actions:
async fetchUsers( commit , config)
const users = await this.$api.users.fetch(config);
commit(ADD_USERS, users);
console.log( message: "Vuex 中的用户数据", users );
,
async createPost( commit , post)
const id = await this.$api.posts.post(post);
commit(ADD_POST,...post, id );
console.log( message: "创建文章", post:...post, id);
,
async updatePost( commit , post)
const id = await this.$api.posts.put(post.id, post);
commit(UPDATE_POST, post);
console.log( message: "更新文章", post:post, id);
);
结语为什么要这么写?
【实战,Vue 项目中,将 API “类化”】本瓜以为:如果你的业务是按照这种类的方式有作区分,那么 API 也应该同步如此。一是思路清晰,跟着业务走;二是扩展性和复用性都更好;三是看起来就很高级......
推荐阅读
- 华为防火墙私网用户通过NAT No-PAT访问Internet(无定向server)
- ROS2 Humble测试版功能包列表
- 服务器数据恢复服务器重装系统导致XFS文件系统分区丢失无法访问的数据恢复案例
- Vmware Horizon( 在ESXI7.0 上面安装windows server 2016)
- 一次奇怪的服务器响应延时分析
- #yyds干货盘点# 解决剑指offer(最小的K个数)
- 什么是智慧矿山(它能解决什么问题?)
- 揭秘 Kotlin 1.6.20 重磅功能 Context Receivers
- 基于IP地址和端口的安全策略