preface

[classes] and [interfaces] are the future of JavaScript, and so will our API calls, sorting and upgrading with business modules in this direction. This article is about — Vue Magician, how to “class” an API?

Everything is a module, everything can be classified. Talk less and get to the point.

Classification of the API

  • Environment: Vue2+ or Vue3+

Let’s build VueCLI quickly and quickly

vue create vue-api-module
Copy the code

You get the following directory

--src
----store
------index.js
----App.vue
----main.js
Copy the code

Then create a new file api.js like this,

--src
----services
------api.js
----store
------index.js
----App.vue
----main.js
Copy the code

Base class API

Let’s start by creating a base class like this:

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) {// Handle the error: console.log({message: "Errors is handled here", err}); }}Copy the code
  • BaseUrl: sets the request root path;
  • Resource C.
  • GetUrl: get the link function, including baseUrl, resource, id;
  • HandleErrors: handle error function;

Read-only class API

Then we create a subclass that contains the fetch and GET read-only methods.

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 is invalid "); const response = await fetch(this.getUrl(id)); return await response.json(); } catch (err) { this.handleErrors(err); }}}Copy the code
  • Fetch: Fetch data.
  • Get: Obtains data by id.

Writing class API

Next, we create a subclass that contains read-write methods: POST, PUT, delete

class ModelApiService extends ReadOnlyApiService { constructor(resource) { super(resource); } async post(data = {}) { try { const response = await fetch(this.getUrl(), { method: "POST", body: JSON.stringify(data) }); const { id } = response.json(); return id; } catch (err) { this.handleErrors(err); } } async put(id, data = {}) { if (! Id) Throw Error(" id is invalid "); try { const response = await fetch(this.getUrl(id), { method: "PUT", body: JSON.stringify(data) }); const { id: responseId } = response.json(); return responseId; } catch (err) { this.handleErrors(err); } } async delete(id) { if (! Id) Throw Error(" id is invalid "); try { await fetch(this.getUrl(id), { method: "DELETE" }); return true; } catch (err) { this.handleErrors(err); }}}Copy the code
  • Post: create data;
  • Put: Update data;
  • Delete: delete data;

inheritance

Let’s look at two simple inheritance examples:

class UsersApiService extends ReadOnlyApiService { constructor() { super("users"); }}Copy the code
class PostsApiService extends ModelApiService { constructor() { super("posts"); }}Copy the code

[UsersApiService] inherits the ReadOnlyApiService API, and can use fetch and get methods. The PostsApiService class inherits the read-write API — ModelApiService, and can use fetch, get, POST, PUT, delete five methods.

We can also write inheritance API classes based on the business:

class AlbumsApiService extends ModelApiService { constructor() { super("albums"); } async uploadImage() {/* here you can write your uploadImage logic */ console.log({message: "image uploaded successfully!" }); return true; } async triggerError() {try {throw Error(" API module call Error! ") ); } catch (err) { this.handleErrors(err); }}}Copy the code

export

We export these apis in api.js:

export const $api = {
  users: new UsersApiService(),
  posts: new PostsApiService(),
  albums: new AlbumsApiService()
};
Copy the code

Classification API Practices

How do I call the above API classes in a Vue project? We call it mainly in Vuex and Components:

storePlugins

  1. First create a storeplugins.js:
--src
----plugins
------storePlugins.js
----services
------api.js
----store
------index.js
----App.vue
----main.js
Copy the code
  1. Introduce api.js in storeplugins.js:
import { $api } from "@/services/api"; export default function(store) { try { store.$api = $api; } catch (e) { console.error(e); }}Copy the code
  1. Introduce the plugin in SRC /store/index.js:
. import storePlugins from "@/plugins/storePlugins"; . export default new Vuex.Store({ plugins: [storePlugins], state: { ... });Copy the code

mixins

  1. Create mixins.js in the following location:
--src
----plugins
------mixins.js
------storePlugins.js
----services
------api.js
----store
------index.js
----App.vue
----main.js
Copy the code
  1. Mixins. Js:
import Vue from "vue";
import { $api } from "@/services/api";

Vue.mixin({
  computed: {
    $api: () => $api
  }
});
Copy the code
  1. Main.js introduces mixins globally:
. import "@/plugins/mixins"; .Copy the code

call

OK! Now you can call it in store and Components, for example:

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()
Copy the code

The sample

Can be debugged locally ~

  • The components of the
<template> <div id="app"> <h1>Vue API "class" example </h1> <p> Please open the console </p> <p> check Vuex Store </p> </div> </template> <script> export Default {name: "App", async created() {// obtain await this.$store.dispatch("fetchUsers"); const users = await this.$api.users.fetch({}); console.log({ message: "Users from the component", users }); Const user = await this.$api.users.get(1); console.log({ message: "User with id: 1", user }); Let post = {userId: 1, title: "test article ", body:" test article "}; await this.$store.dispatch("createPost", post); Post = {... post, id: 1 }; await this.$store.dispatch("updatePost", post); $api.posts.delete(post.id); // Delete "await" this. Console. log({message: "Successfully deleted article!" }); // Execute the custom method await this.$api.albums. UploadImage (); // Execute the custom method 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>Copy the code
  • In the 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 user data ", users}); }, async createPost({ commit }, post) { const id = await this.$api.posts.post(post); commit(ADD_POST, { ... post, id }); Console. log({message: "create article ", post: {... post, id } }); }, async updatePost({ commit }, post) { const id = await this.$api.posts.put(post.id, post); commit(UPDATE_POST, post); Console. log({message: "update post ", post: {post, id}}); }}});Copy the code

conclusion

Why did you write it that way?

If your business is differentiated in this way, then the API should be synchronized as well. One is clear thinking, follow the business; Second, scalability and reusability are better; Third, it looks very advanced…… 😀 😀 😀

  • ordinary
Export const getPost = params => {return axios.get(' /interface/getPost/ ') params => { return axios.post(`/interface/addPost`, Export const updatePost = params => {return axios.post(' /interface/updatePost/ ', params)}......Copy the code
import {getPost,addPost,updatePost} from '@/services/api'
Copy the code
  • senior
class PostsApiService extends ModelApiService { constructor() { super("posts"); }}Copy the code
this.$api.posts.post(param)
Copy the code

This time to here, I am the nuggets Anthony, the person is not malicious, also many words! Public number [Nuggets Anthony].

Thumbs up small manual move, you and I forward together ~ goodbye ~