Vue之Axios跨域问题解决方案

背景:因为axios中只能使用get和post方法来进行请求数据,没有提供jsonp等方法进行跨域访问数据

          axios中文网址:https://www.kancloud.cn/yunye/axios/234845

// axios 中的GET请求
axios.get('/user', {
    params: {
      ID: ‘001’
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// axios 中的POST请求
axios.post('/user', {
    firstName: '1',
    lastName: '2'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

方案1:既然使用axios直接进行跨域访问不可行,我们就需要配置代理了。代理可以解决的原因:因为客户端请求服务端的数据是存在跨域问题的,而服务器和服务器之间可以相互请求数据,是没有跨域的概念(如果服务器没有设置禁止跨域的权限问题),也就是说,我们可以配置一个代理的服务器可以请求另一个服务器中的数据,然后把请求出来的数据返回到我们的代理服务器中,代理服务器再返回数据给我们的客户端,这样我们就可以实现跨域访问数据。

准备工作:安装所需中间件和插件等,比如axios,http-proxy-middleware等。

具体案例:这里以访问豆瓣Top250为例,直接访问如下:

axios.get("http://api.douban.com/v2/movie/top250")
.then(res=>{
	console.log(res)
})
.catch(err=>{
	console.log(err)
})

当执行npm run dev时,控制台报错如下:

事实证明直接请求确实出现跨域问题了,下面具体演示解决跨域问题的步骤:

上面所说的必备条件都已安装完成的情况下,执行以下步骤即可解决问题:

1.配置BaseUrl

在main.js中,配置数据所在服务器的前缀(即固定部分),代码如下:

// 项目入口,配置全局vue
import Vue from 'vue'
import VueRouter from './router/routes.js'
import Store from './store/index.js'

import './assets/less/index.less'
import App from './App.vue'


import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'

import axios from 'axios'
Vue.prototype.$axios = axios
axios.defaults.baseURL = '/api'  //关键代码
Vue.config.productionTip = false


Vue.use(ElementUI);

new Vue({
	router:VueRouter,
	store:Store,
	template:'<App/>',
	components: {App}
}).$mount('#app')

// 默认进入商品模块
// VueRouter.push({ path: '/home' })

关键代码:axios.defaults.baseURL = '/api',作用是我们每次发送的请求都会带一个/api的前缀。

2.配置代理

在config文件夹下的index.js文件中的proxyTable字段中,作如下处理:

  dev: {
    env: require('./dev.env'),
    port: 8090,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        target:'http://api.douban.com/v2', // 你请求的第三方接口
        changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
        pathRewrite:{  // 路径重写,
          '^/api': ''  // 替换target中的请求地址,也就是说以后你在请求http://api.douban.com/v2/XXXXX这个地址的时候直接写成/api即可。
        }
      }
    },
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }

3.在具体使用axios的地方,修改url如下即可:

 axios.get("/movie/top250").then((res) => {
                  res = res.data
                  if (res.errno === ERR_OK) {
                     this.themeList=res.data;
                  }
                }).catch((error) => {
                  console.warn(error)
                })

4.重新启动项目之后,已经解决了跨域问题,结果如下:

原理:

因为我们给url加上了前缀/api,我们访问/movie/top250就当于访问了:localhost:8080/api/movie/top250(其中localhost:8080是默认的IP和端口)。

在index.js中的proxyTable中拦截了/api,并把/api及其前面的所有替换成了target中的内容,因此实际访问Url是http://api.douban.com/v2/movie/top250。

至此,纯前端配置代理解决axios跨域得到解决。

方案2:后端处理跨域问题,加个过滤器即可解决,如下:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 跨域过滤器
 * @author jitwxs
 * @since 2018/10/16 20:53
 */
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        // 不使用*,自动适配跨域域名,避免携带Cookie时失效
        String origin = request.getHeader("Origin");
        if(StringUtils.isNotBlank(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
        }

        // 自适应所有自定义头
        String headers = request.getHeader("Access-Control-Request-Headers");
        if(StringUtils.isNotBlank(headers)) {
            response.setHeader("Access-Control-Allow-Headers", headers);
            response.setHeader("Access-Control-Expose-Headers", headers);
        }

        // 允许跨域的请求方法类型
        response.setHeader("Access-Control-Allow-Methods", "*");
        // 预检命令(OPTIONS)缓存时间,单位:秒
        response.setHeader("Access-Control-Max-Age", "3600");
        // 明确许可客户端发送Cookie,不允许删除字段即可
        response.setHeader("Access-Control-Allow-Credentials", "true");
        
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void destroy() {
    }

    /*
    注册过滤器:
    @Bean
    public FilterRegistrationBean registerFilter() {
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
        bean.addUrlPatterns("/*");
        bean.setFilter(new CorsFilter());
        // 过滤顺序,从小到大依次过滤
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);

        return bean;
    }
     */
}

以上axios解决跨域的方案,希望能解决大家遇到的跨域问题,如有问题请添加评论。

-------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------

根据评论区内容,区分一下生产环境和开发环境,集体配置如下:

1.在config文件夹里面创建一个api.config.js的配置文件

const isPro = Object.is(process.env.NODE_ENV, 'production')

console.log(isPro);

module.exports = {
  baseUrl: isPro ? 'https://www.***/index.php/Official(线上地址)' : 'api/'
}

2.在main.js文件里面引入上面文件,这样就可以保证动态的匹配生产和开发环境的定义前缀了,代码如下:

import Vue from 'vue'
import App from './App'
import router from './router'
import 'bootstrap/dist/js/bootstrap.min'
import 'bootstrap/dist/css/bootstrap.min.css'
import axios from 'axios'
import apiConfig from '../config/api.config'

Vue.prototype.$axios = axios;
Vue.config.productionTip = false;
axios.defaults.baseURL = apiConfig.baseUrl;// 配置接口地址
axios.defaults.withCredentials = false;

以上两步即可解决vue的跨域问题,并且可以可以直接build打包到线上,如有问题,请评论区留言,希望对你有所帮助。

<think>好的,用户想解决Axios问题,我需要根据提供的引用内容来整理答案。首先,问题的产生是因为浏览器的同源策略,前后端分离项目常见这个问题。引用里提到了几种解决方法,包括前端配置代理和后端允许。 用户问的是如何使用Axios解决,所以可能需要分前端和后端两个方面来回答。前端方面,Vue项目可以通过配置代理,修改config/index.js中的proxyTable,这样开发环境下请求会被代理,绕过限制。另外,Axios的请求拦截器可以处理POST数据格式,如使用qs库转换参数,避免格式问题导致的错误。 后端方面,SpringBoot可以使用@CrossOrigin注解或者在配置类中添加CORS配置,设置允许的源、方法、头信息等。这样后端明确允许请求,浏览器就不会拦截了。 需要检查引用中的内容,确保步骤准确。比如引用3提到了前端配置代理的步骤,引用2和4提到了后端注解和配置类的方法。同时,安装Axios和拦截器的使用也是需要注意的点。 可能用户是前端开发者,所以需要详细说明前端代理的设置步骤,但也要提到后端配置的必要性,因为有时候仅前端代理是不够的,尤其在生产环境。需要分点回答,结构清晰,步骤明确,让用户能一步步操作。 另外,生成的相关问题需要和Axios使用相关,比如如何配置代理、拦截器的作用、生产环境部署的注意事项等。确保问题覆盖用户可能遇到的后续疑问。</think>### 使用 Axios 解决请求问题的步骤 #### 一、前端配置(Vue 项目) 1. **安装 Axios** 在 Vue 项目中通过 npm 安装 Axios: ```bash npm install axios --save ``` 2. **配置代理(开发环境)** 修改 `config/index.js` 文件,添加代理规则以解决问题: ```javascript dev: { proxyTable: { '/api': { // 代理路径标识符(可自定义) target: 'http://localhost:8080', // 后端接口地址 changeOrigin: true, // 允许 pathRewrite: { '^/api': '' // 移除代理路径标识符 } } } } ``` 此时前端请求 `/api/data` 会被代理到 `http://localhost:8080/data`[^3]。 3. **配置请求拦截器(处理 POST 数据格式)** 在 `main.js` 中配置 Axios 拦截器,自动转换 POST 请求参数为 `x-www-form-urlencoded` 格式: ```javascript import axios from 'axios'; import qs from 'qs'; axios.interceptors.request.use(config => { if (config.method === 'post') { config.data = qs.stringify(config.data); } return config; }); ``` 需安装 `qs` 库:`npm install qs`。 --- #### 二、后端配置(Spring Boot 示例) 1. **单接口允许** 在 Controller 方法上添加 `@CrossOrigin` 注解: ```java @RestController public class UserController { @CrossOrigin(origins = "http://localhost:8080") // 允许指定源 @GetMapping("/data") public String getData() { return "response data"; } } ``` 2. **全局配置** 创建配置类实现全局支持: ```java @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8080") // 允许的源 .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法 .allowedHeaders("*") // 允许的请求头 .allowCredentials(true); // 允许携带凭证(如 cookies) } } ``` 此配置对所有接口生效[^2][^4]。 --- #### 三、完整请求示例 ```javascript // 前端请求代码(Vue 组件) axios.get('/api/data') .then(response => { console.log(response.data); }) .catch(error => { console.error(error); }); ``` --- ### 关键原理 1. **开发环境代理**:通过 Vue CLI 的代理配置,将请求转发到后端接口,绕过浏览器同源策略限制。 2. **CORS 机制**:后端通过响应头 `Access-Control-Allow-Origin` 声明允许的源,浏览器收到响应后解除拦截[^2]。 ---
评论 114
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值