目录

前景:

安装axios

封装

简单封装(不推荐)

二次封装(推荐)

顺序请求

方式一:async结合await 

方式二:then

常用请求的前后端写法

get请求

路径参数方式,传入的参数是变量

params 路径拼接方式:传入的参数是一个复杂对象

params 路径拼接方式:传入的参数是一个变量

post请求:

参数在请求体中

基于代理配置多环境(解决跨域)

创建环境配置文件

配置代理

修改axios请求配置

启动时选择当前环境


前景:

在做期末作业的时候,老师布置的是做一个前后端分离的项目,我们后端采用spring boot,前端采用vue,前后端通信的是axios请求,记录一下

我看评论区有说跨域的问题,我新增了一段代理内容,一并解决吧

安装axios

输入命令:

npm install axios

封装

新建一个request.js文件,命名随意,注意我这里的提示信息使用了element框架,如果读者没有安装可以删掉相关代码,还有tokenUtil文件,如果读者不需要token直接删掉即可

import axios from 'axios' 
import { getToken } from '@/utils/tokenUtil'
import { Message } from 'element-ui'//此处是element-ui如果是plus则是'element-plus'
// 创建axios实例
const request = axios.create({
    // 这里可以放一下公用属性等。
    baseURL: 'http://localhost:8099', // 用于配置请求接口公用部分,请求时会自动拼接在你定义的url前面。
    withCredentials: false, // 跨域请求时是否需要访问凭证
    timeout: 3 * 1000, // 请求超时时间

})

// 请求拦截器
request.interceptors.request.use((config) => {
//token名称以自己的为定,我的是‘token’,如果不需要if这里就可以直接删掉
    if (getToken('token')) {
        config.headers['token'] = getToken('token'); //携带token
    }
    config.headers['Content-type'] = 'application/json';
    return config;
}, (error) => {
    return Promise.reject(error)
})

request.interceptors.response.use((response) => {
//返回码以自己的为定,如果没有安装elementui就换成自己的提示
    let { code, msg } = response.data
    if (code != 200) {
        Message({ message: msg || 'error', type: 'warning' })
    }
    return response.data;//此处可以只返回后端传出的数据(第一层data是axios封装的)
}, (error) => {
    return Promise.reject(error)
})

export default request;//记得暴露出去

上面的代码有关于tokenUtil.js相关代码:在utils目录下新建一个tokenUtil.js文件(这里演示就存在localStorage里面,真实情况推荐存在cookie里面)

export function setToken(tokenKey, token) {
    return localStorage.setItem(tokenKey, token)
}
export function getToken(tokenKey) {
    return localStorage.getItem(tokenKey)
}
export function removeToken(tokenKey) {
    return localStorage.removeItem(tokenKey)
}

简单封装(不推荐)

将配置好的request挂载到vue原型上,无需引入,在全局就能使用

在main.js中添加:


import request from '@/utils/request.js'//引入请求配置文件
....main.js中其他内容

Vue.prototype.$request=request//$不是必要的,只是习惯将原型上的属性用$表示

....main.js中其他内容

在页面中使用:

methods:{
    login(){
        this.$request.post("/login",this.loginForm).then(res=>{
            ....逻辑处理
        }
    }
}

缺点:

1、请求路径编写在各个页面中,难以维护,如果后端更改请求路径,修改难度极大

2、无法重用,同一个请求会多次编写

二次封装(推荐)

封装api请求内容:

新建一个api文件夹,里面用于封装api请求,命名随意

我的目录如下

内容如下:

import request from "@/request";//记得引入上面封装的request文件

export function login(data) {
    return request({
        method: 'post',
        url: '/business/login',
        data: data //可以简写为data
    })
}

页面中使用:

vue2:

<script>
import { login } from "@/api/index.js";//引入
import {setToken} from "@/utils/tokenUtil"

export default {
  methods: {
//调用封装的login请求,将前端用户填写的数据传递
     login(this.formlogin).then((res) => {
          console.log(res.data);
            setToken(res.data.token)//保存后端传来的token
         })
    }
}
</script>

vue3:(语法糖方式) 

顺序请求

有时候会需要发送一个请求后再发送另一个请求获取数据。虽然获取数据尽量包含在一个请求,但还是难免有这种需要。由于axios(ajax)是异步请求,如果我们顺序调用它并不能保证前面一个请求完成后再调用下一个。所以需要我们进行简单的更改一下

下面演示均是采用vue3写法,如果是vue2则不用function

方式一:async结合await 

async function test(){
 let res=await login(数据)
     ...//  对res进行处理
  let res2=await getLoginUserInfo()
      ...//对res2进行处理
//请求三如上
}

方式二:then

方式1 
function test(){
     login(数据).then(res=>{
     ...//  对res进行处理
        getLoginUserInfo().then(res2=>{
   ...//对res2进行处理,请求三继续在内部调用
        })
    })
}
方式2
 function test(){
     login(数据).then(res=>{
     ...//  对res进行处理
       return getLoginUserInfo() //将下一次请求return
    }).then(res2=>{
       ...//对res2进行处理,
         //此处如果再次reture一个请求,
        })//则此处又可以.then()了
}

常用请求的前后端写法

get请求

路径参数方式,传入的参数是变量

export function Body(page,size) {
    return request({
        method: 'get',
        url: '/commoditys/'+page+"/"+size
//      url:`/commoditys/${page}/${size}`//使用模板字符串语法,注意是``而不是‘’
    })
}

后端接收对应的方式

     @GetMapping("/commoditys/{page}/{size}")
    public AjaxJson QueryCommoditys(@PathVariable("page") int page, @PathVariable("size") int size) {
        PageInfo commoditys = commodityService.queryCommoditys(page, size);
        return AjaxJson.getSuccessData(commoditys);
    }

params 路径拼接方式:传入的参数是一个复杂对象

skuSearchDto :{
  categoryId: '',
  brandId: '',
  state: '',
  searchValue: '',
  minPrice: 0,
  maxPrice: 0,
  pageNum: 1,
  pageSize: 5,
  totals: 0
}


export function getSkuList(skuSearchDto) {
    return request({
        method: 'get',
        url: goodsBase + `get/sku/page`,
        params: skuSearchDto
    })
}

后端接收方式

 实体接收(注意实体类接收不能使用@RequestParam注解)

 @GetMapping("get/sku/page")
    public R getSkuList(SkuSearchDto skuSearchDto) {
        IPage list = goodsService.getSkuList( skuSearchDto);
        return RUtils.successData(list);
    }

map接收

 @GetMapping("get/sku/page")
    public R getSkuList(@RequestParam Map<String,String> skuSearchDto) {
        IPage list = goodsService.getSkuList( skuSearchDto);
        return RUtils.successData(list);
    }

params 路径拼接方式:传入的参数是一个变量

export function getCommodityAttributeInfo(commodityId) {
    return request({
        method: 'get',
        url: '/getCommodityAttribute',
        params: {
            commodityId
        }
    })
}

或者可以手动拼接

export function getCommodityAttributeInfo(commodityId) {
    return request({
        method: 'get',
        url: '/getCommodityAttribute?commodityId=' + commodityId,
    })
}

 后端接收使用@RequestParam注解即可

@GetMapping("getCommodityAttribute")
R getCommodityAttribute(@RequestParam String commdityId){
//内部逻辑

}

post请求:

参数在请求体中

export function addCommodityAttributeValues(data) {
    return request({
        method: 'post',
        url: '/addCommodityAttributeValue',
        data
    })
}

后端接收:@RequestBody注解

  @PostMapping("addSingleCommodity")
    public AjaxJson addSingleCommodity(@RequestBody SingleCommodity singleCommodity){
        singleCommodityService.addSingleCommodity(singleCommodity);
        return AjaxJson.getSuccess();
    }

当然post也可以使用params,包括delete,put请求都一样

例如

export function enroll(data,params={}) {
    return request({
        method: 'post',
        url: '/user/enroll',
        data ,
        params
    })
}

基于代理配置多环境(解决跨域)

一般项目分为开发、测试、生产等多种环境,对应的后端地址可能不同,所以建议采用多环境配置。

vue也提供了对应的配置文件,默认环境:.env;开发环境:.env.development;生产环境:.env.production;测试环境:.env.test;等

注:这些命名都是规定的,如果想要自己自定义,你可以在 vue.config.js 文件中配置 webpack 的 DefinePlugin 来手动加载 .env.xxx 文件中的变量(不推荐)

创建环境配置文件

新建一个.env.development文件,.env.production文件(以这俩环境为例)

# 开发环境
NODE_ENV = 'development'

# 开发环境,默认BASEURL
VUE_APP_BASE_URL = '/api'

# 开发环境,API前缀
VUE_APP_BASE_API = '/api'

#开发环境,Url地址(后端地址)
VUE_APP_BASE_TARGET = 'http://localhost:10001/'

其中配置必须以VUE_APP开头。

配置代理

const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
    transpileDependencies: true,
    lintOnSave: false,
    devServer: {
        proxy: {
            [process.env.VUE_APP_BASE_API]: {
                //请求转发
                target: process.env.VUE_APP_BASE_TARGET,
                //转发时将前缀"/api"去掉
                pathRewrite: {['^' + process.env.VUE_APP_BASE_API]: ""}
            }
        }
    }
})

修改axios请求配置

找到我们之前创建的request.js文件,将发送请求地址更改为前缀

启动时选择当前环境

通过“ --model 环境配置文件”   命令指定运行时采用的环境

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐