如何发起跨域资源请求
[用于 Nuxt.js 的 http-proxy 中间件解决方案](https://github.com/nuxt-community/proxy-module#readme)
引入 axios 和 proxy
npm i @nuxtjs/proxy -D
// 如果创建项目没有选择axios
npm install @nuxtjs/axios
我直接引入的axios
yarn add axios
在 nuxt.config.js 配置文件中添加对应的模块,并设置代理
export default {
plugins: ['@/plugins/axios'],
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
proxy: true
},
proxy: {
'/api': {
target: 'http://192.168.11.111:8080',
// pathRewrite: {
// "^/": "",
// },
// secure: false,
// changeOrigin: true,
}
}
}
nuxt 的 axios 封装及调用
直接使用
注意:请求接口不需要写 http://192.168.11.111:8080 这个写在 proxy 里,否则 get 请求会报跨域错误
let resData4 = await this.$axios.$post('/cg_class/Search/page', {})
console.log('resData.result4------', resData4)
let resData3 = await this.$axios.$get('/cg_class/subject', {})
console.log('resData.result3------', resData3)
二次封装
1. 在plugins下新建 axios.js
import homeApi from "./api/home";
import videoApi from "./api/video";
import orderApi from "./api/order";
export default function ({ app, $axios, store }, inject) {
// console.log("store", store.state);
const API = {};
$axios.onRequest((config) => {
// 相关配置
config.headers["X-Access-Token"] = app.$cookies.get("token") || "";
});
API.homeApi = homeApi($axios);
API.videoApi = videoApi($axios);
API.orderApi = orderApi($axios);
// Inject to context as $api
inject("api", API);
}
2. 在plugins下新建 api 文件夹, 里面新建 home.js,
export default ($axios) => ({
// 头部 分类列表
subject(data) {
return $axios.$get("/cg_class/subject", data);
},
// 头部 搜索 检索分页
searchPage(data) {
return $axios.$post("/cg_class/Search/page", data);
},
});
3. 引入
plugins: [
"@/plugins/axios",
]
4. 使用方法
<template>
<div>
<div style="margin: 20px 0">
{{ searchData }}
</div>
<div>
{{ subjectData }}
</div>
</div>
</template>
<script>
export default {
data () {
return {
searchData: '',
subjectData: '',
}
},
// 服务端 post
// async asyncData ({ $api }) {
// let searchData = await $api.homeApi.searchPage({}).then((resData) => {
// // console.log("resData---1", resData.result.records);
// return resData.result.records.slice(0, 1)
// })
// return { searchData }
// },
// 服务端 get
// async asyncData ({$api}) {
// let subjectData = await $api.homeApi.subject({}).then((resData) => {
// // console.log("resData---2", resData.result);
// return resData.result
// })
// subjectData.subjectList = []
// return { subjectData }
// },
// async fetch ({ store }) {
// let Token = store.state.Token
// return {
// Token
// }
// },
// Promise
async asyncData ({ $api }) {
let { subjectData, searchData } = await Promise.all([$api.homeApi.subject({}), $api.homeApi.searchPage({})]).then(([res1, res2]) => {
return {
subjectData: res1.result,
searchData: res2.result.records.slice(0, 1)
}
})
subjectData.subjectList = []
return {
subjectData,
searchData
}
},
mounted () {
// this.init1()
// this.init2()
},
methods: {
// 客户端 post
init1 () {
this.$api.homeApi.searchPage({}).then((resData) => {
console.log('searchPage---', resData.result.records)
this.searchData = resData.result.records.slice(0, 1)
})
},
// 客户端 get
init2 () {
this.$api.homeApi
.subject({})
.then((resData) => {
console.log('subject---', resData.result)
this.subjectData = resData.result
this.subjectData.subjectList = []
})
},
},
}
</script>
使用 原生的axios
注意:这里将 nuxt.config.js下的 plugins 改为: plugins: ['@/plugins/index'],
否则会报错 Maximum call stack size exceeded
注意:这种方式暂时无法解决请求头携带 token 的问题(服务端请求获取不到token), 所以不推荐。
1.封装axios。在plugins下新建 axios.js
import axios from "axios";
import { Message } from "element-ui";
import { state } from "@/store";
var CancelToken = axios.CancelToken;
function requireAxios(url) {
// console.log('process.server', process.server)
// 本地开发 发现get请求不能有url,但是post得有,不清楚原因,所以写了个这
if (process.client) {
url = "";
}
const serveice = axios.create({
baseURL: url,
timeout: 6000,
});
//设置拦截
//请求拦截
serveice.interceptors.request.use(
//设置请求头
(config) => {
//开始loading
startLoading();
// 本地开发 客户端请求 state.Token可以拿到,但是服务端拿不到,还没解决,先这样用着
config.headers["X-Access-Token"] =
state.Token ||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDc4MzAwNzAsInVzZXJuYW1lIjoiYWRtaW4ifQ.lLfETxxlSRX2v9pnuqMWDctt92t1nRMFSW3e4SzaDkg";
// addLoading();
// console.log('params', params)
if (config.method == "get" || config.method == "delete") {
// console.log("config.data", config.data);
config.params = config.data;
delete config.data;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
//响应拦截
serveice.interceptors.response.use(
(response) => {
//结束loading
endLoading();
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 服务器状态码不是200的情况
(error) => {
//结束loading
endLoading();
console.log("error.response---", error);
var messageTxt = "";
if (error && error.response) {
switch (error.response.status) {
case 1067: //token失效
messageTxt = "";
localStorage.clear();
break;
case 404:
// `请求地址出错: ${error.response.config.url}`
messageTxt = `请求地址出错`;
break;
case 408:
messageTxt = "请求超时!";
break;
case 500:
messageTxt = "服务器内部错误!";
break;
default:
messageTxt = "异常问题,请联系管理员!";
break;
}
// if (error.messageTxt.includes('timeout')) messageTxt = '网络请求超时!'
// if (error.messageTxt.includes('Network'))
// messageTxt = window.navigator.onLine
// ? '服务端异常!'
// : '请检查您的网络!'
Message.error(messageTxt, 5);
}
return Promise.reject(error.response);
}
);
return serveice;
}
export default requireAxios;
/**
* 封装axios
*/
console.log("process.env.BASE_URL", process.env.BASE_URL);
let baseInstance = requireAxios(process.env.BASE_URL); //http://192.168.50.226:8080
export function request(params) {
return new Promise((resolve, reject) => {
// 取消请求
params.cancelToken = new CancelToken(function (cancel) {});
baseInstance(params)
.then(({ data }) => {
if (data.code === 200) {
resolve(data);
} else {
reject(data);
}
})
.catch((err) => {
reject(err);
});
});
}
/**
* loading
* **/
function startLoading() {
// 开始加载
// Toast.loading({
// messageTxt: "加载中...",
// forbidClick: true
// });
}
function endLoading() {
// 结束加载
// Toast.clear()
}
2.导出请求文件并区分模块。在 plugins 下新建 index.js
/**
* api导出
*/
// import Vue from 'vue'
import homeApi from './api/home' // 接口文件
var API = {
homeApi,
}
// 如果用 prototype 将无法在服务端使用
// Vue.prototype.$api = api
export default ({ app, $axios }, inject) => {
app.api = API
inject('api', API)
}
3.接口文件。在 plugins 下新建 api 文件夹,api文件夹里新建home.js
import serveice, { request } from '../axios'
let serveiceAxios = serveice(process.env.PAY_BASE_URL) //如若有多个服务器地址
const homeApi = {
// 分页
searchPage: (data) =>
request({
url: '/cg_class/Search/page',
data,
method: 'post',
}),
// 视频播放
getPlayAuth: (data) =>
request({
url: '/cg_class/video/get-play-auth',
data,
method: 'get',
}),
// 课程 查询所有分类
subject: (data) =>
request({
url: '/cg_class/subject',
data,
method: 'get',
}),
}
export default homeApi
4.使用方法
<template>
<div>
<div style="margin-bottom: 20px">
{{ searchData }}
</div>
<div>
{{ subjectData }}
</div>
</div>
</template>
<script>
export default {
data () {
return {
searchData: '',
subjectData: '',
}
},
// 服务端 post
async asyncData (ctx) {
let searchData = await ctx.app.api.homeApi.searchPage({}).then((resData) => {
console.log("resData---1", resData.result);
return resData.result
})
return { searchData }
},
// 服务端 get
async asyncData (ctx) {
let subjectData = await ctx.app.api.homeApi.subject({}).then((resData) => {
// console.log("resData---2", resData.result);
return resData.result
})
return { subjectData }
},
// Promise
async asyncData (ctx) {
let { subjectData, searchData } = await Promise.all([ctx.app.api.homeApi.subject({}), ctx.app.api.homeApi.searchPage({})]).then(([res1, res2]) => {
console.log("res1---", res1.result);
console.log("res2---", res2.result);
return {
subjectData: res1.result,
searchData: res2.result
}
})
console.log("subjectData---", subjectData);
console.log("searchData---", searchData);
return {
subjectData,
searchData
}
},
mounted () {
this.init1()
this.init2()
},
methods: {
// 客户端 post
init1 () {
this.$api.homeApi.searchPage({}).then((resData) => {
console.log('searchPage---', resData.result.records)
this.searchData = resData.result
})
},
// 客户端 get
init2 () {
this.$api.homeApi
.subject({})
.then((resData) => {
console.log('subject---', resData.result)
this.subjectData = resData.result
})
},
},
}
</script>
<style lang="stylus" scoped></style>