前言
写项目,跨域永远是个绕不开的问题,除非自己在localhost上玩.以前总是后端用cors的方式去解决这个问题.老问题,后端如果没整,怎么玩?写vue项目,常用vue-cli工具依照webpack模板去搭一个项目结构.每个人都知道用npm run dev 启动项目,但是更应该知道的是我们是依赖了webpack-dev-server代理服务器(用node.js写的)才启动了这个项目.没亲手设置可不代表不存在.所以才会在vue项目中有服务器代理这种配置项.补一句:二手资料害死人.
问题描述:
使用 Vue-cli 创建的项目,(前端)开发地址是 localhost:8080,需要访问 (后端)上的接口并不是这个,例如后端地址是http://192.168.199.168:8080/ ,数据访问是要跨域的哟!
抄来的方案:(先说说网上抄来抄去的一个手法)
1.在 config文件夹下index.js文件 的 dev 中添加配置项 proxyTable:
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
// 我们家的接口就不用api这种前缀,要怎样
'/api': {
target: 'http://192.168.199.168:8080/',
changeOrigin: true,
// 为什么不能说说pathRewrite到底是干什么的呢
// 就知道要'^/api': '/'或者'^/api': '/'
// 以及'/'和''有什么区别
// 哎,二手资料害死人
pathRewrite: {
'^/api': '/'
}
}
},
2.使用axios插件时,发的请求
axios.get('/api/yyd-manage/department/list')
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
注:
1.使用了 axios,可以全局配置一个 baseURL,这样就不用挨个儿修改 url 了,可以省掉请求时的'/api',如:axios.get('/yyd-manage/department/list').
axios.defaults.baseURL = '/api'
//放在main.js文件中或者自己写一个js插件文件,在main.js中注册一下
这种手法可去你的吧,这属于强行操作
2.其中 '/api' 为匹配项,target 为被请求的地址
3.因为在 ajax 的 url 中加了前缀 '/api',而原本的接口是没有这个前缀的 所以需要通过 pathRewrite 来重写地址,将前缀 '/api' 转为 '/' 如果本身的接口地址就有 '/api' 这种通用前缀,就可以把 pathRewrite 删掉
上述操作全属于无脑抄袭,也就能骗骗我这种水货,完全不具备实用性
解决方案:
先看后端node服务器的一段简易代码
/*
express框架是nodeJS的第三方模块 express框架实际上是对http模块的高度封装
*/
// 相当于引入了http模块
const express = require('express');
// 创建web服务器
const app = express();
// 当客户端以get方式请求/的时候
app.get('/index', (req, res) => {
// express提供给我们的用来做响应的方法
res.send('首页')
})
app.get('/list', (req, res) => {
res.send('列表页')
})
app.get('/article', (req, res) => {
res.send('文章页')
})
app.post('/getUserInfo', (rep, res) => {
res.send('用户详情');
})
// 监听端口
app.listen(3000, () => {
console.log('服务器启动成功');
});
例:其中的一个接口地址为:http://localhost:3000/index
vue-cli搭的webpack项目模板中前端设置服务器代理的代码
//在 config文件夹下index.js文件 的 dev 中添加配置项 proxyTable
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/index': {
target: 'http://localhost:3000/',
changeOrigin: true,
// 就不写pathRewrite
}
},
axios的get别名请求方法代码
//随便找个组件写个点击事件,发请求
axios.get('/index')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
})
返回内容(跨域成功)
注:
1.proxyTable中的'/index'相当于一个标识,告诉webpack-dev-server,我的请求接口中以/index开头的地址要使用代理.不然的话, 可能你的 html, css, js这些静态资源都跑去代理. 所以我们只要接口用代理, 静态文件用本地.极端情况下你使用'/',那么所有的请求都会被代理,当然也可以正常跨域.
2.使用这种服务器代理的方式跨域时,不需要再去设置axios的基地址了,会报错. 即不用axios.get('http://localhost:3000/index')也不用axios.defaults.baseURL = 'http://localhost:3000/' 然后axios.get('/index')
3.proxyTable的配置项是webpack模板作者自己定义的,实际上真正生效的是webpack的devServer.proxy配置项,在build文件夹下webpack.dev.conf.js可以看到proxy: config.dev.proxyTable,靠这行代码实现的真正配置.iview-admin模板的vue.config.js中正是直接使用devServer.proxy而不是proxyTable,才让我在两个项目模板上困惑不已.
参考文章:vue-cli的webpack相关内容
参考文章:webpack的DevServer
4.pathRewrite的作用:
pathRewrite相当于一个重定向或者叫重写请求路径的作用,当然也可以移除,添加.
这是隶属于插件http-proxy-middleware的东西,该插件功能强大,还有路由等功能.
上一段配置代码(修改配置项要注意重启项目)
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/index': {
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
// 符号^是正则表达式符号,是匹配输入字符串的开始位置
'^/index': '/list'
}
}
},
本来我们要请求http://localhost:3000/index的接口现在就成了请求http://localhost:3000/list
axios的get别名请求方法代码
//随便找个组件写个点击事件,发请求
axios.get('/index')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
})
返回结果(是接口/list的结果,而不是/index的)
项目中的配置文件还是应当好好研究一下,不仅仅是跨域问题,还有开发模式,测试模式,生产模式,process.env等环境变量,路还很远.明年就要正式更新vue3.0了,变化真快.