Vue Learning (7) - Introducing Axios

foreword

Vue official website recommends using Axios for Ajax calls. This article describes how to introduce Axios into a Vue project.

Prepare the server program

This server program is only used for testing. If readers have other rest interfaces for testing, they can skip this section.

I create a Springboot project through Eclipse. First create a new maven

Select the item webapp

Fill in the necessary information to complete

Modify the pom.xml file, mainly to increase the dependence on spring-boot and spring-mvc. The place where the first few lines are commented out is my project information, readers can change it to their own.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<!--	改成你的项目信息
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.sadoshi.springboot</groupId>
	<artifactId>SpringbootTest</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringbootTest Maven Webapp</name>
	<url>http://maven.apache.org</url>
-->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.2</version>
		<relativePath />
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-maven-plugin</artifactId>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

Add a new directory java under the src/main folder, and create a new main class App.java

package com.sadoshi.springboottest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.sadoshi.springboottest.App;

@SpringBootApplication
public class App {

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

Create a new controller processing class HelloController.java as the rest interface:

package com.sadoshi.springbootABC;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {

	@RequestMapping("")
	public String test() {
		return "test HelloController";
	}
	
	@PostMapping("/name")
	public String name(@RequestBody String name) {
		return "hello " + name;
	}
}

Start the App class, and then the browser calls http://localhost:8080/hello , if the following page appears, it means success:

Create a new Vue project

As before, let's create a new Vue project and install dependencies:

vue create axios1
cd axios1
npm install

Remember, do not set the project name to "axios", otherwise when installing axios dependencies, the installation dependencies will fail due to the same name.

Then install the axios dependency

npm install axios --save

Introduce axios in main.js and add it to the global environment, so that you don't need to import it in every component that needs to use axios.

import Vue from 'vue'
import App from './App.vue'

import axios from 'axios'
Vue.prototype.$axios = axios
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

Simplify App.vue and remove redundant information

<template>
  <div id="app">
    <HelloWorld/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
</style>

HelloWorld.vue is modified to:

<template>
  <div class="hello">
    <button @click="onHello">测试</button>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data() {
    return {
      name: '',
    }
  },
  methods: {
    onHello(){
      this.$axios.get("/hello").then(res => {
        console.log(res);
      })
    }
  }

}
</script>

<style scoped>
</style>

Start the project and see the following interface:

Click the test button to call the backend interface http://localhost:8080/hello, we click f12 to view the debugging information:

Seeing the error message means cross-domain. Obviously, calling localhost:8080 at localhost:8081 is cross-domain. So how do we deal with it?

Handle cross domain issues

Mainly through proxy solutions. Usually in the project, our front-end call will add a prefix, usually "api", modify main.js:

import Vue from 'vue'
import App from './App.vue'

import axios from 'axios'
Vue.prototype.$axios = axios
Vue.config.productionTip = false

axios.defaults.baseURL = '/api'


new Vue({
  render: h => h(App),
}).$mount('#app')

After adding the content in line 8, for the relative path , the subsequent axios calls will be prefixed with api (the absolute path will not change). Then we set up the proxy and create the vue.config.js file (same level as the src and package.json directories) under the project root path.

module.exports = {
  devServer: {
      proxy: {
          '/api': {
              target: 'http://localhost:8080/',
              // 允许跨域
              changeOrigin: true,
              pathRewrite: {
                  '^/api': ''
              }
          }
      }
  }
}

The above means that for the call of the prefix api, the request is replaced with a call to http://localhost:8080/ . Remember to add the prefix http here .

Modify HelloWorld.vue, change axios call to use relative path

<template>
  <div class="hello">
    <button @click="onHello">测试</button>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data() {
    return {
      name: '',
    }
  },
  methods: {
    onHello(){
      this.$axios.get("/hello").then(res => {
        console.log(res);
      })
    }
  }

}
</script>

<style scoped>
</style>

Re-run the project, and then click the button, you can see that the call is successful

However, the amount of information returned above is a bit large, and it will be cumbersome to process various returned information in the business code (for example, what to do when 200 is returned, what to do when 400 is returned, and what to do when 500 is returned, especially some nested calls .So usually the returned information is encapsulated, and only data processing is done in the business layer.

Encapsulate axios call

Wrapping axios is usually implemented using axios interceptors. However, the encapsulation is related to the information returned by the rest interface and how the reader's application should handle exceptions. Here is a simple encapsulation. Create a new utils directory under the src directory, and create a new request.js under the src/utils directory:

import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: '/api',
  // 超时
  timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
  return config
}, error => {
    console.log(error)
    Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
    // 未设置状态码则默认成功状态
    const code = res.data.code || 200;
    // 获取错误信息
    const message = res.data.msg
    if (code === 401) {
      MessageBox.confirm(
        '登录状态已过期,您可以继续留在该页面,或者重新登录',
        '系统提示',
        {
          confirmButtonText: '重新登录',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
        // store.dispatch('LogOut').then(() => {
        //   location.reload() // 为了重新实例化vue-router对象 避免bug
        // })
      })
    } else if (code === 500) {
      Message({
        message: message,
        type: 'error'
      })
      return Promise.reject(new Error(message))
    } else if (code !== 200) {
      Notification.error({
        title: message
      })
      return Promise.reject('error')
    } else {
      return res.data
    }
  },
  error => {
    console.log('err' + error)
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service

The above code introduces element ui, an open source component, mainly how to prompt the front end when exception handling occurs. Readers can also make corresponding prompts according to their own needs, or comment out the lines related to element ui. Since the baseURL has been set in line 8, the sentence "axios.defaults.baseURL = '/api'" in line 8 of main.js can be deleted.

Usually the actual project’s calls to the background are defined in the api directory. For example, we create a new directory api under src, and create a new hello.js under the directory:

import request from '../utils/request'

export function hello() {
  return request({
    url: '/hello',
    method: 'get'
  })
}

export function sayHello(data) {
  return request({
    url: '/hello/name',
    method: 'post',
    data: data
  })
}

Then modify HelloWorld.vue

<template>
  <div class="hello">
    <button @click="onHello">测试</button>
    名字:<input v-model="name" />
    <button @click="onName">发送</button>
  </div>
</template>

<script>
import { hello, sayHello } from '@/api/hello'

export default {
  name: 'HelloWorld',
  data() {
    return {
      name: '',
    }
  },
  methods: {
    onHello(){
      hello().then(res => {
        console.log(res)
      })
    },
    onName(){
      sayHello(this.name).then(res => {
        console.log(res)
      })
    }
  }

}
</script>

<style scoped>
</style>

After starting the project, test the effects of the two buttons separately. For a successful call, only data is returned, and the business layer does not need to process cumbersome return information.

summary:

The use of axios is very simple. In most cases, as long as the project is packaged, the packaged request can be called directly. Generally, there is no need to write axios.

Guess you like

Origin blog.csdn.net/sadoshi/article/details/122637510