[Front-end series No. 8] Vue+axios: An article, explaining all the knowledge of axios

        Vue is a progressive JavaScript framework that allows you to create user interfaces and interaction logic with a concise syntax. However, if you want to develop a complete web application, you also need to be able to interact with the back-end server for data, such as getting data, sending data, updating data or deleting data. At this time, you need to use an HTTP client library to help you send asynchronous requests and process responses.

        In this article, I will introduce a very popular and practical HTTP client library - axios, which allows you to easily implement data interaction functions in Vue. I will show the basic concept and usage of axios, as well as the relationship and difference between it and Vue. I will also give some practical examples to demonstrate how to use axios to get data, send data, update data and delete data. Finally, tell you how to handle errors and cancel requests in axios.


Table of contents

1. What is axios

2. How to install axios

3. API and convenient methods of axios

4. How to use axios in Vue?

(1) Import and use axios directly in the component

(2) Bind axios on the prototype

(3) Use the vue-axios plugin

5. How to get data with axios?

6. How to send data with axios?

7. How to update data with axios?

8. How to delete data with axios?

9. How to handle errors with axios?

10. How to cancel a request with axios?

 11. Best practices for Vue and axios


1. What is axios

axios is a Promise-based HTTP client library, it can be used in the browser and node.js, it allows you to easily send asynchronous requests and handle responses. Axios has the following advantages:

  • Supports browser and node.js
  • Support Promise API
  • Support for intercepting requests and responses
  • Support for transforming request and response data
  • Support Cancellation Request
  • Support automatic conversion of JSON data
  • Support client defense against XSRF

axios is an independent library, it does not depend on any other library or framework, so you can use it anywhere. However, if you want to use axios with Vue, you need to do some additional configuration and packaging to make it better integrated with Vue.

2. How to install axios

There are two ways to install axios, one is to install through npm or yarn, and the other is to introduce through a CDN link. If you are using a project created by Vue CLI, then you can use the first method to install axios. Just run the following command in the project root directory:

npm install axios --save
# 或者
yarn add axios

This will add axios to your project dependencies, and you can import and use it from anywhere.

If you don't use Vue CLI to create a project, or you just want to quickly test the functions of axios, then you can use the second way to import axios. Just add the following tags to your HTML file:

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

This will load and execute the axios code from the CDN link, and the axios object can be accessed on the global variable window.

3. API and convenient methods of axios

axios provides a generic method to send any kind of HTTP request:

axios(config)

Among them, config is an object that contains relevant configuration information of the request, such as url, method, data, headers, etc. For example:

// 发送一个POST请求
axios({
  method: 'post',
  url: '/user',
  data: {
    firstName: 'Alice',
    lastName: 'Smith'
  }
});

In addition to the general methods, axios provides some convenience methods to send specific types of HTTP requests:

// 发送一个GET请求(默认方法)
axios(url[, config])

// 发送一个GET请求,并传递查询参数
axios.get(url[, config])

// 发送一个POST请求,并传递请求体数据
axios.post(url[, data[, config]])

// 发送一个PUT请求,并传递请求体数据
axios.put(url[, data[, config]])

// 发送一个PATCH请求,并传递请求体数据
axios.patch(url[, data[, config]])

// 发送一个DELETE请求
axios.delete(url[, config])

// 发送一个HEAD请求
axios.head(url[, config])

// 发送一个OPTIONS请求
axios.options(url[, config])

These convenience methods allow you to send HTTP requests more concisely without specifying the request method each time. For example:

// 发送一个GET请求
axios('/user');

// 等价于
axios({
  method: 'get',
  url: '/user'
});

No matter which method you use to send HTTP requests, axios will return a Promise object, you can use the then method to handle a successful response, or use the catch method to handle a failed response. For example:

// 发送一个GET请求,并处理响应
axios.get('/user')
  .then(function (response) {
    // 处理成功的响应
    console.log(response);
  })
  .catch(function (error) {
    // 处理失败的响应
    console.log(error);
  });

If you're using ES6 syntax, you can use arrow functions to simplify your code:

// 发送一个GET请求,并处理响应(ES6)
axios.get('/user')
  .then(response => {
    // 处理成功的响应
    console.log(response);
  })
  .catch(error => {
    // 处理失败的响应
    console.log(error);
  });

If you are using ES7 syntax, you can use async/await to simplify the code:

// 发送一个GET请求,并处理响应(ES7)
async function getUser() {
  try {
    const response = await axios.get('/user');
    // 处理成功的响应
    console.log(response);
  } catch (error) {
    // 处理失败的响应
    console.log(error);
  }
}

4. How to use axios in Vue?

There are several ways to use axios in Vue:

  • Import and use axios directly in the component
  • Bind axios on the prototype to make it available in all components
  • Use the vue-axios plugin to integrate axios into the Vue instance

Let's look at some concrete examples:

(1) Import and use axios directly in the component

This is the easiest way, you only need to import axios in the component that needs to send the request, and call its method. For example, suppose we have a UserList component that needs to fetch a list of users from the backend and display it on the page. We can write like this:

<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {
   
   { user.name }}
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      users: []
    };
  },
  mounted() {
    // 发送GET请求获取用户列表
    axios.get('/user')
      .then(response => {
        // 将响应数据赋值给users
        this.users = response.data;
      })
      .catch(error => {
        // 处理错误
        console.log(error);
      });
  }
};
</script>

The advantage of this method is that it is simple and clear, and does not require additional configuration. The disadvantage is that axios needs to be imported every time, and global interception or conversion cannot be conveniently performed.

(2) Bind axios on the prototype

This way you can access axios via this.$http in all components without having to import it every time. You just need to bind axios on the prototype before creating the Vue instance. For example, in the main.js file:

import Vue from 'vue';
import axios from 'axios';

// 在原型上绑定axios
Vue.prototype.$http = axios;

new Vue({
  // ...
});

Then, in any component, you can use it like this:

this.$http.get('/user')
  .then(response => {
    // ...
  })
  .catch(error => {
    // ...
  });

The advantage of this method is that it is convenient for unified management and does not need to be imported repeatedly. The disadvantage is that it may cause prototype pollution, or conflict with other libraries.

(3) Use the vue-axios plugin

This way allows you to access axios through this.axios or this.$http in all components, and you can use Vue's plug-in mechanism for some global configuration. You need to install the vue-axios plugin first:

npm install vue-axios --save

Then, before creating the Vue instance, use the Vue.use method to install the plugin, passing in axios as a parameter. For example, in the main.js file:

import Vue from 'vue';
import axios from 'axios';
import VueAxios from 'vue-axios';

// 使用vue-axios插件
Vue.use(VueAxios, axios);

new Vue({
  // ...
});

Then, in any component, you can use it like this:

this.axios.get('/user')
  .then(response => {
    // ...
  })
  .catch(error => {
    // ...
  });

// 或者

this.$http.get('/user')
  .then(response => {
    // ...
  })
  .catch(error => {
    // ...
  });

The advantage of this approach is that it can be better integrated with Vue, taking advantage of Vue's lifecycle hooks and reactive system. The disadvantage is that an additional plugin needs to be installed, or it conflicts with other plugins.

5. How to get data with axios?

Obtaining data is the most common data interaction operation in web applications, and it usually corresponds to the GET method of HTTP. Using axios to get data is very simple, just call the axios.get method and pass in the requested URL. For example, suppose we have a UserDetail component which needs to fetch user details from the backend and display them on the page. We can write like this:

<template>
  <div>
    <h1>用户详情</h1>
    <p>姓名:{
   
   { user.name }}</p>
    <p>年龄:{
   
   { user.age }}</p>
    <p>邮箱:{
   
   { user.email }}</p>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      user: {}
    };
  },
  props: {
    userId: {
      type: Number,
      required: true
    }
  },
  mounted() {
    // 发送GET请求获取用户详情
    axios.get(`/user/${this.userId}`)
      .then(response => {
        // 将响应数据赋值给user
        this.user = response.data;
      })
      .catch(error => {
        // 处理错误
        console.log(error);
      });
  }
};
</script>

Here, we use props to receive the userId parameter passed by the parent component, and then splice it into the requested URL. We also use template strings (backticks) to simplify string concatenation. Note that if you are using ES5 syntax, you need to use string concatenation (+) to concatenate strings.

When we send a GET request, the backend server will return a response object, which contains the following properties:

  • data: response body data, usually an object or an array
  • status: response status code, such as 200, 404, 500, etc.
  • statusText: Response status text, such as OK, Not Found, Internal Server Error, etc.
  • headers: response header information, such as Content-Type, Content-Length, etc.
  • config: request configuration information, such as url, method, data, headers, etc.

We can access these properties through the response parameter in the then method and process them as needed. For example, we can print out the response status code and response header information:

axios.get('/user')
  .then(response => {
    // 打印响应状态码和响应头信息
    console.log(response.status);
    console.log(response.headers);
    // ...
  })
  .catch(error => {
    // ...
  });

If we only care about the response body data, we can access it directly using response.data and assign it to the component's data property. For example, we can assign a list of users to the users property:

axios.get('/user')
  .then(response => {
    // 将响应体数据赋值给users属性
    this.users = response.data;
  })
  .catch(error => {
    // ...
  });

Sometimes, we need to pass some query parameters when sending GET requests, such as paging, sorting, filtering, etc. We can use the params attribute to specify query parameters, which is an object that contains key-value pairs. For example, we can pass the page and size parameters to get the user list on the second page, and each page displays 10 pieces of data:

axios.get('/user', {
  params: {
    page: 2,
    size: 10
  }
})
  .then(response => {
    // ...
  })
  .catch(error => {
    // ...
  });

In this way, axios will automatically convert the params object into a query string and splice it into the URL, such as /user?page=2&size=10.

6. How to send data with axios?

Sending data is another common data interaction operation in Web applications, which usually corresponds to the POST, PUT, PATCH or DELETE methods of HTTP. It is also very simple to use axios to send data, just call the corresponding method and pass in the requested URL and data. For example, suppose we have a UserForm component that needs to add or update a user's information from the backend. We can write like this:

<template>
  <div>
    <h1>用户表单</h1>
    <form @submit.prevent="submitForm">
      <label>姓名</label>
      <input v-model="user.name" required>
      <label>年龄</label>
      <input v-model.number="user.age" required>
      <label>邮箱</label>
      <input v-model="user.email" required>
      <button type="submit">提交</button>
    </form>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      user: {}
    };
  },
  props: {
    userId: {
      type: Number,
      default: null
    }
  },
  mounted() {
    // 如果有userId参数,说明是更新用户信息,需要先获取用户详情
    if (this.userId) {
      axios.get(`/user/${this.userId}`)
        .then(response => {
          // 将响应数据赋值给user
          this.user = response.data;
        })
        .catch(error => {
          // 处理错误
          console.log(error);
        });
    }
  },
  methods: {
    submitForm() {
      // 如果有userId参数,说明是更新用户信息,需要发送PUT请求
      if (this.userId) {
        axios.put(`/user/${this.userId}`, this.user)
          .then(response => {
            // 处理成功的响应
            console.log(response);
          })
          .catch(error => {
            // 处理失败的响应
            console.log(error);
          });
      } else {
        // 如果没有userId参数,说明是添加用户信息,需要发送POST请求
        axios.post('/user', this.user)
          .then(response => {
            // 处理成功的响应
            console.log(response);
          })
          .catch(error => {
            // 处理失败的响应
            console.log(error);
          });
      }
    }
  }
};
</script>

Here, we use the v-model directive to implement two-way binding of form input and component data. We also use the @submit.prevent modifier to prevent the form's default submit behavior and call the custom submitForm method to send the request.

When we send a POST, PUT, PATCH or DELETE request, the backend server will return a response object, which is the same as the response object returned by the GET request, including data, status, statusText, headers, config and other attributes. We can access these properties through the response parameter in the then method and process them as needed. For example, we can print out the response status code and response body data:

axios.post('/user', this.user)
  .then(response => {
    // 打印响应状态码和响应体数据
    console.log(response.status);
    console.log(response.data);
  })
  .catch(error => {
    // ...
  });

If we only care about the response status code, we can directly use response.status to access it, and perform different operations based on different values. For example, we can display different prompts according to the response status code:

axios.post('/user', this.user)
  .then(response => {
    // 根据响应状态码显示不同的提示信息
    if (response.status === 201) {
      alert('用户添加成功');
        //...
}

7. How to update data with axios?

Updating data is an operation to modify existing data in a Web application, and it usually corresponds to the PUT or PATCH method of HTTP. Using axios to update data is similar to sending data, you only need to call the corresponding method and pass in the requested URL and data. The difference is that the PUT method will replace the entire resource, while the PATCH method will only modify part of the resource. For example, suppose we have a UserForm component that needs to update the user's information from the backend. We can write like this:

<template>
  <div>
    <h1>用户表单</h1>
    <form @submit.prevent="submitForm">
      <label>姓名</label>
      <input v-model="user.name" required>
      <label>年龄</label>
      <input v-model.number="user.age" required>
      <label>邮箱</label>
      <input v-model="user.email" required>
      <button type="submit">提交</button>
    </form>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      user: {}
    };
  },
  props: {
    userId: {
      type: Number,
      required: true
    }
  },
  mounted() {
    // 发送GET请求获取用户详情
    axios.get(`/user/${this.userId}`)
      .then(response => {
        // 将响应数据赋值给user
        this.user = response.data;
      })
      .catch(error => {
        // 处理错误
        console.log(error);
      });
  },
  methods: {
    submitForm() {
      // 发送PUT请求更新用户信息
      axios.put(`/user/${this.userId}`, this.user)
        .then(response => {
          // 处理成功的响应
          console.log(response);
        })
        .catch(error => {
          // 处理失败的响应
          console.log(error);
        });
    }
  }
};
</script>

Here, we have used the PUT method to update the user information, which will replace the entire user object with the new value. If we only want to modify some attributes of the user, such as age, we can use the PATCH method to update the user information, which will only modify the specified attributes. For example:

// 发送PATCH请求更新用户年龄
axios.patch(`/user/${this.userId}`, { age: this.user.age })
  .then(response => {
    // 处理成功的响应
    console.log(response);
  })
  .catch(error => {
    // 处理失败的响应
    console.log(error);
  });

Here, we only pass an object containing the age attribute as the request body data, which will only modify the user's age attribute without affecting other attributes.

8. How to delete data with axios?

Deleting data is an operation to remove existing data in a web application, and it usually corresponds to the DELETE method of HTTP. Using axios to delete data is also very simple, just call the axios.delete method and pass in the requested URL. For example, let's say we have a UserList component that needs to delete users' information from the backend. We can write like this:

<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {
   
   { user.name }}
        <button @click="deleteUser(user.id)">删除</button>
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      users: []
    };
  },
  mounted() {
    // 发送GET请求获取用户列表
    axios.get('/user')
      .then(response => {
        // 将响应数据赋值给users
        this.users = response.data;
      })
      .catch(error => {
        // 处理错误
        console.log(error);
      });
  },
  methods: {
    deleteUser(userId) {
      // 发送DELETE请求删除用户信息
      axios.delete(`/user/${userId}`)
        .then(response => {
          // 处理成功的响应
          console.log(response);
          // 从users数组中移除该用户
          this.users = this.users.filter(user => user.id !== userId);
        })
        .catch(error => {
          // 处理失败的响应
          console.log(error);
        });
    }
  }
};
</script>

Here, we use the deleteUser method to delete user information, which sends a DELETE request and passes in the user's id as a URL parameter. Then, we also need to remove the user from the users array to maintain data consistency. We can use the filter method to filter out elements with the same user id and return a new array.

9. How to handle errors with axios?

When sending HTTP requests, various errors may be encountered, such as network errors, server errors, client errors, etc. It is also very simple to use axios to handle errors, just use the catch method to catch the exception, and pass in a callback function to handle the error. For example:

axios.get('/user')
  .then(response => {
    // ...
  })
  .catch(error => {
    // 处理错误
    console.log(error);
  });

In the catch method, we can access the error object through the error parameter, which contains the following properties:

  • message: error message, such as Network Error, Request failed with status code 404, etc.
  • config: request configuration information, such as url, method, data, headers, etc.
  • request: request object, such as XMLHttpRequest or http.ClientRequest, etc.
  • response: response object, such as data, status, statusText, headers, etc.

We can judge the type and cause of the error according to different attributes, and deal with it accordingly. For example, we can display different prompts according to the response status code:

axios.get('/user')
  .then(response => {
    // ...
  })
  .catch(error => {
    // 处理错误
    if (error.response) {
      // 如果有响应对象,说明服务器返回了错误的响应
      switch (error.response.status) {
        case 400:
          alert('请求参数错误');
          break;
        case 401:
          alert('未授权,请登录');
          break;
        case 403:
          alert('拒绝访问');
          break;
        case 404:
          alert('请求地址不存在');
          break;
        case 500:
          alert('服务器内部错误');
          break;
        default:
          alert('未知错误');
      }
    } else if (error.request) {
      // 如果有请求对象,说明请求没有成功发送或没有收到响应
      alert('网络错误,请检查网络连接');
    } else {
      // 如果没有请求对象,说明是其他原因导致的错误
      alert('发生了一些错误,请稍后重试');
    }
  });

10. How to cancel a request with axios?

When sending an HTTP request, sometimes we may need to cancel the request that has been sent, such as the user clicking the cancel button, or the page jumping, etc. It is also very simple to use axios to cancel the request. You only need to use the CancelToken object to create a cancellation token and pass it into the configuration of the request. For example:

// 创建一个取消令牌源
const source = axios.CancelToken.source();

// 发送一个GET请求,并传入取消令牌
axios.get('/user', {
  cancelToken: source.token
})
  .then(response => {
    // ...
  })
  .catch(error => {
    // 处理错误
    if (axios.isCancel(error)) {
      // 如果是由于取消令牌导致的错误,说明请求已经被取消了
      console.log('Request canceled', error.message);
    } else {
      // 如果是其他原因导致的错误,正常处理
      console.log(error);
    }
  });

// 在某个时机调用取消令牌源的cancel方法来取消请求
source.cancel('Operation canceled by the user.');

In this way, when we call the source.cancel method, axios will automatically cancel the request and throw an error object. We can use the axios.isCancel method to determine whether the error is caused by the cancellation token, and then handle it accordingly.

 11. Best practices for Vue and axios

When using axios in Vue, there are several aspects to pay attention to:

  • Encapsulate axios: In order to facilitate management and maintenance, we can encapsulate the configuration, interception, conversion and other functions of axios into a separate file, and then import and use it where needed. This avoids duplication of code and also handles errors and exceptions uniformly.
  • Use environment variables: In order to adapt to different development and deployment environments, we can use environment variables to configure the base URL, timeout, request header and other information of axios. This avoids hard coding and also allows flexibility to switch between different environments.
  • Use modularity: In order to improve the readability and maintainability of the code, we can separate different business logic into different modules, and then import and use them where needed. This avoids confusion and allows easy reuse and extension.
  • Use async/await: In order to simplify the writing and reading of asynchronous code, we can use async/await syntax to replace Promise chain calls. This avoids callback hell and also allows for better handling of errors and exceptions.

Let's look at a simple example, how to use the best practice of axios in Vue:

First, we create an axios.js file to encapsulate the configuration, interception, conversion and other functions of axios:

// 导入axios
import axios from 'axios';

// 创建一个axios实例
const instance = axios.create({
  // 使用环境变量来配置基础URL
  baseURL: process.env.VUE_APP_BASE_URL,
  // 使用环境变量来配置超时时间
  timeout: process.env.VUE_APP_TIMEOUT,
  // 使用环境变量来配置请求头
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${process.env.VUE_APP_TOKEN}`
  }
});

// 添加请求拦截器
instance.interceptors.request.use(config => {
  // 在发送请求之前做些什么,比如添加加载动画
  console.log('开始发送请求');
  return config;
}, error => {
  // 对请求错误做些什么,比如提示错误信息
  console.log('请求失败');
  return Promise.reject(error);
});

// 添加响应拦截器
instance.interceptors.response.use(response => {
  // 对响应数据做点什么,比如移除加载动画
  console.log('接收到响应');
  return response;
}, error => {
  // 对响应错误做点什么,比如提示错误信息
  console.log('响应失败');
  return Promise.reject(error);
});

// 导出封装好的axios实例
export default instance;

Then, we create a user.js file to encapsulate user-related business logic:

// 导入封装好的axios实例
import axios from './axios';

// 定义一个获取用户列表的方法
export const getUserList = async () => {
  try {
    // 使用async/await语法来发送GET请求,并处理响应
    const response = await axios.get('/user');
    // 返回响应数据
    return response.data;
  } catch (error) {
    // 处理错误
    console.log(error);
    // 抛出异常
    throw error;
  }
};

// 定义一个添加用户的方法
export const addUser = async user => {
  try {
    // 使用async/await语法来发送POST请求,并处理响应
    const response = await axios.post('/user', user);
    // 返回响应数据
    return response.data;
  } catch (error) {
    // 处理错误
    console.log(error);
    // 抛出异常
    throw error;
  }
};

// 定义一个更新用户的方法
export const updateUser = async (userId, user) => {
  try {
    // 使用async/await语法来发送PUT请求,并处理响应
    const response = await axios.put(`/user/${userId}`, user);
    // 返回响应数据
    return response.data;
  } catch (error) {
    // 处理错误
    console.log(error);
    // 抛出异常
    throw error;
  }
};

// 定义一个删除用户的方法
export const deleteUser = async userId => {
  try {
    // 使用async/await语法来发送DELETE请求,并处理响应
    const response = await axios.delete(`/user/${userId}`);
    // 返回响应数据
    return response.data;
  } catch (error) {
    // 处理错误
    console.log(error);
    // 抛出异常
    throw error;
  }
};

Finally, we import and use the methods in the user.js file in the required components, such as the UserList component:

<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {
   
   { user.name }}
        <button @click="deleteUser(user.id)">删除</button>
      </li>
    </ul>
  </div>
</template>

<script>
// 导入用户相关的方法
import { getUserList, deleteUser } from './user';

export default {
  data() {
    return {
      users: []
    };
  },
  async mounted() {
    // 使用async/await语法来获取用户列表,并赋值给users属性
    this.users = await getUserList();
  },
  methods: {
    async deleteUser(userId) {
      // 使用async/await语法来删除用户,并从users数组中移除该用户
      await deleteUser(userId);
      this.users = this.users.filter(user => user.id !== userId);
    }
  }
};
</script>

In this way, we use the best practices of Vue and axios, making our code more concise, clear, readable, maintainable and extensible.

This article is over here, have you learned enough~

Guess you like

Origin blog.csdn.net/TaloyerG/article/details/132388814