本文的知识点:vue-cli3配置proxy解决跨域(涉及内容什么是跨域,跨域的原理,跨域的解决。axios的封装,axios请求的封装,封装函数在组件中的具体使用,添加请求拦截器,添加响应拦截器)
跨域问题是前端开发中较常见的问题,因为javascript的浏览器会支持同源策略,如果域名、协议、端口任意不同就会产生跨域。当页面在执行一个脚本时,会检查访问的资源是否同源,如果不是,就会报错。可是在实际开发中,经常会有跨域加载资源的需求,避免不了跨域请求,所以就出现了跨域。错误信息如下:Access to XMLHttpRequest at ‘http://baidu.cn/api/b1/auth/login’ from origin ‘http://localhost:8000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource。
同源策略限制的具体表现是什么?
(1)coikie、LocalStorage和Index DB 无法读取
(2)Dom 无法获得
(3)AJAX请求不能发送
JS中自带跨域技能的标签是什么 ?
JS中有两个神奇的标签,从出生起就自带跨域技能,就是<img/>
和<script><script/>
这两个标签。
说起能跨域的标签,就要提一提常用的跨域方法。
常用的跨域方法是什么?
1、JSONP – 原理就是利用了script标签,在标签外套了一层壳,利用标签特性达到跨域加载资源的效果。
JSONP由两部分组成,回调函数和数据
2、CORS – 跨站资源共享,它是跨域的官方解决方案,升级版的JSONP。原理是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。请求和响应都不包含cookie信息。
3、webSockets – 不受同源策略影响。原理是因为它不使用HTTP协议,而使用一种自定义的协议,专门为快速传输小数据设计。
4、Nginx – 代理跨域。反向代理跨域。
下面我说说我在实际开发过程运用的代理(对于大型项目,我们可能需要配置多个请求的域名即baseUrl,我在此也是了两个服务器)
通过 vue.config.js 中的 devServer.proxy 选项来配置,增加如下代码:
devServer: {
module.exports = {
publicPath:'./',
devServer: {
proxy: {
'/schedule': {
target: 'http://156.14.232.151:8087', //要请求的域名
changeOrigin: true,//开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
ws:true
},
'/datax': {
target: 'http://156.14.232.151:8069', //要请求的域名
changeOrigin: true,//开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
ws:true,
}
}
}
}
我们对接口的请求都是用/schedule和/datax作为前缀,可以统一在request.js的baseURL中处理(根据实际情况处理,在这里还可以对axios请求进行简单的封装.)
const axios = require('axios')
import { Message, Loading } from 'element-ui'
const instance = axios.create({
headers:{ 'Content-Type': 'application/json;chartset=utf-8' ,'token': 'JSON.parse(sessionstorage.getItem("token")'},
baseURL: '/schedule', // '/schedule'等于http://156.14.232.151:8087,写一个一样的js文件,将baseUrl换成 '/datax',前面后后面步骤不变
timeout: 30000, // 请求超时时间30000
transformRequest:[(data)=>{
return JSON.stringify(data);
}],
transformResponse:[data=>{
return JSON.parse(data);
}],
// proxy: {
// host: '172.17.1.61',
// port: 3000,
// },
// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
withCredentials:true,
// `responseType` indicates the type of data that the server will respond with
// options are 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
// responseType: 'json', // default
});
// 添加请求拦截器
service.interceptors.request.use(config => {
loadingInstance = Loading.service({
lock: true,
text: 'loading...'
})
return config
})
// 添加响应拦截器
service.interceptors.response.use(response => {
loadingInstance.close()
// console.log(response)
return response.data
}, error => {
console.log('TCL: error', error)
const msg = error.Message !== undefined ? error.Message : ''
Message({
message: '网络错误' + msg,
type: 'error',
duration: 3 * 1000
})
loadingInstance.close()
return Promise.reject(error)
})
export default instance
vue2.0 配置方法
proxyTable: {
'/api': {
target: 'http://baidu.com/', // 请求的接口的域名
// secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
pathRewrite: {
'^/api': ''
}
}
}
第二步:封装请求(在实际开发中,页面调用接口比较多而且复杂时,我们都会将请求进行一次封装。可以对模块建一个request.js文件,这里面放的是具体请求)
import service from './instance'
//数据源列表
function getMetaData(params){
return service({
method:'get',
url:'/meta/getMeta',
params
})
}
//数据源管理列表
function getSourceTable(params){
return service({
method:'get',
url:'/jdbc/jdbcs',
params
})
}
export{
getMetaData,
getSourceTable,
}
第三步:使用
在vue组件中
import {,getSourceTable} from '@/api/request.js'
//监控列表
getSourceData(){
let pageNo = this.pageNo;
let pageSize = this.pageSize;
getMetaData({
...this.formData,
pageNo,pageSize
}).then(res=>{
//console.log(res);
if(res.data.code == 200){
this.tableData = res.data.data.list;
this.pageTotal = res.data.data.total;
}
})
},