


一.先下载axios依赖
- npm install axios
二.在需要的地方引入
- import axios from 'axios'
三.环境准备好了之后就可以使用axios调用接口了
简单语法:
axios.get("url",{参数}).then(function(response){
});
例子:
四.解决跨域
如果直接这样调用是会存在跨域的
在webpack.config.js中的devServer去配置跨域。或者是vue.config.js,或者config文件夹下的index.js文件中配置。版本不同配置文件会不一样,比如:vue-cli2.0时代,webpack的配置文件写在config/index.js 文件,vue-cli3.0时代,没了config文件夹,vue.config.js写在项目的根目录下
- devServer: {
- historyApiFallback: true,
- noInfo: true,
- proxy: {
- '/api': {
- changeOrigin: true,
- target: 'http://m.tnblog.net/api/v1/home/1'
- },
- '/myapi': {
- changeOrigin: true,
- target: 'http://localhost:7324'
- }
- }
- },
try again在调用试试,这样配置后我们就可以使用/myapi,来替代http://localhost:7324这个地址了。
- axios.get("/myapi/api/dept/6").then(function(response){
- console.log(response);
- });
还是不行会报404的错误
我们在去配置一个pathRewrite,也就是路径重写,就可以解决这个404的问题了
- '/myapi': {
- //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求
- changeOrigin: true,
- target: 'http://localhost:7324',
- pathRewrite:{
- '^/myapi':''
- }
- }
可以看到已经得到结果了
特别注意:修改了配置文件后,把vue服务停止了在重启一下,不然是没有效果的。他这个跨域的解决方法其实就是中间加了一层代理而已
五.全局引用axios
上面的引用方式在需要的地方引用,每次都要引用就会很麻烦,我们可以在main中全局引用一下,其他地方都可以用了
- import axios from 'axios'
- //全局引用axios
- Vue.prototype.$http = axios
然后使用的时候就可以用vue的对象直接点$http出来使用了,这个名字是可以随便取得
例如:
写完收工....准备吃饭
六.请求封装
请求封装可以统一处理一些事情,比如统一的loading处理,统一的token处理,统一请求拦截等。
先在src目录中创建一个common文件夹,然后创建一个request.js文件
先进行一点很简单的封装
- import axios from 'axios'
- import qs from 'qs'
-
-
- const request = {
- get(url, data,_success)
- {
- // 判断有没有参数,有参数就把参数加上
- if(data)
- {
- url = url+ '?' + qs.stringify(data)
- }
- console.log(url)
- axios.get(url).then(function (response) {
- _success(response)
- });
- },
- post(url, data,_success)
- {
- axios.post(url,data).then(function (response) {
- _success(response)
- });
- }
- }
-
- export default request
这里还用到了一点qs做序列化用,需要先安装一下,npm install qs。
然后在main.js中去进去全局引用
- import request from './common/request.js'
- Vue.prototype.$http = request
然后就可以在需要的页面使用了
发送一个get请求
- this.$http.get("/api/v1/Home/1",null,function(response){
- console.log(response)
- })
发送一个post请求
- this.$http.post("/api/v1/Home",{userName:"张三"},function(response){
- console.log(response)
- })
使用Promise封装一下请求,就可以不用传递回调函数了
- import axios from "axios";
- import qs from "qs";
-
- const request = {
- get(url, data) {
- // 判断有没有参数,有参数就把参数加上
- if (data) {
- url = url + "?" + qs.stringify(data);
- }
-
- return new Promise((resolve, reject) => {
- axios.get(url).then(function (response) {
- resolve(response);
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
- post(url, data) {
- return new Promise((resolve, reject) => {
- axios.post(url, data).then(function (response) {
- resolve(response);
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
- };
-
- export default request;
现在调用的时候就不需要传递回调函数了,直接使用then方法即可。
- this.$http.get("/api/v1/Home/1", null).then((res)=>{
- console.log("数据成功回来了")
- console.log(res)
- })
-
- this.$http.post("/api/v1/Home", { userName: "张三" }).then((res)=>{
- console.log("post数据成功回来了")
- console.log(res)
- })
Promise的使用可以参考:https://www.tnblog.net/xiuxin/article/details/8147
然后可以进行一点返回状态判断status为200才是请求成功
封装如下:
- return new Promise((resolve, reject) => {
- axios.get(url).then(function (response) {
- //判断一下请求状态
- if (response.status === 200){
- resolve(response);
- }
- else
- {
- reject(response);
- }
- })
- .catch((e) => {
- reject(e);
- });
- });
还可以和自己后台接口规定的状态一起进行判断,比如我们后台接口规定正确状态的返回为200,我们就可以这样判断。返回的值也可以直接取data之后的了。(tip:这个判断要根据你的实际情况修改判断对哦,不然使用else里边的reject输出,虽然结果也能正确输出,但是浏览器上会提示Uncaught (in promise)),也不能继续正确的向下执行了)。
统一请求拦截
代码如下:
- // 请求拦截器
- axios.interceptors.request.use((axiosconfig) => {
- console.log("进入请求拦截器了")
- console.log(axiosconfig)
- return axiosconfig;
- },
- (err) => {
- return Promise.reject(err);
- }
- );
比如可以做统一的登录验证,统一设置header bearer token,统一请求地址处理等。
- // 请求拦截器
- axios.interceptors.request.use(axiosconfig => {
- // loading.open() // 打开加载窗口
- // 统一访问登录信息。方法内部可以去写如果没有登录就跳转到登录页等逻辑
- var loginfo = utils.getloginfo()
- if (loginfo && loginfo.token) {
- axiosconfig.headers.Authorization = 'Bearer ' + loginfo.token // 统一的token处理
- }
- else{
- // token没有获取到就跳转到登录页,跳转的地址不要接域名本地开发环境就跳转到开发环境,线上就自动跳转到线上
- location.href = "/#/login?redirect=/school-dashboard#/index";
- }
-
- // 统一请求地址处理。统一增加一个前缀
- axiosconfig.url = config.serverhost + axiosconfig.url
- return axiosconfig
- },
- err => {
- //loading.close() // 关闭加载窗口
- return Promise.reject(err)
- }
- )
这类统一的处理其实就很类似后台的过滤器,中间件这类的东西,可以统一的实现一些逻辑。
统一响应拦截
代码如下:
- // 响应拦截器
- axios.interceptors.response.use((response) => {
- console.log("统一响应了")
- return response;
- },
- (err) => {
- return Promise.reject(err);
- }
- );
你要进行什么统一响应的处理写到这里即可,比如统一的错误提示,统一的后台接口状态码处理,统一的token错误过期处理等,就不用写到每个请求封装里边了。
还可以进行统一的超时时间设置,或者是请求格式设置等
- axios.defaults.timeout = 300000 // 设置超时时间
- // 配置请求头数据格式
- axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
还可以不直接使用默认的axios对象,而且是创建一个新的
比如:下面的代码就是创建了一个新的axios对象,并且统一设置了baseURL以及超时时间,baseURL从环境变量里边读取的,就可以做到比如线下开发环境请求接口的时候需要加上一个前端,发布后就不需要前缀了
- // create an axios instance
- const service = axios.create({
- baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
- // withCredentials: true, // send cookies when cross-domain requests
- timeout: 60000 // request timeout
- // maxContentLength: Infinity // 客户端不限制大小
- })
创建了一个新的对象后,封装的代码就不直接使用axios对象了,而是使用刚刚创建的service对象,例如统一的请求拦截处理
- service.interceptors.request.use(
- config => {
- // If-Modified-Since:0 IE浏览器缓存强制过期A
- config.headers['If-Modified-Since'] = 0
- // 用于权限菜单用
- config.headers['m-id'] = router?.app?._route?.meta?.id ?? 0
- // do something before request is sent
- if (store.getters.token) {
- // let each request carry token
- // ['X-Token'] is a custom headers key
- // please modify it according to the actual situation
- config.headers['Authorization'] = 'Bearer ' + getToken()
- }
-
- return config
- },
- error => {
- // do something with request error
- console.log(error) // for debug
- return Promise.reject(error)
- }
- )
贴一个目前稍微完整一点的
- import axios from "axios";
- import qs from "qs";
-
- axios.defaults.timeout = 300000 // 设置超时时间
- // 配置请求头数据格式
- // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
-
- // 请求拦截器
- axios.interceptors.request.use((axiosconfig) => {
- console.log("进入请求拦截器了")
- console.log(axiosconfig)
- return axiosconfig;
- },
- (err) => {
- return Promise.reject(err);
- }
- );
-
- // 响应拦截器
- axios.interceptors.response.use(
- (response) => {
- console.log("统一响应了");
- return response;
- },
- (err) => {
- return Promise.reject(err);
- }
- );
-
- const request = {
- get(url, data) {
- // 判断有没有参数,有参数就把参数加上
- if (data) {
- url = url + "?" + qs.stringify(data);
- }
-
- return new Promise((resolve, reject) => {
- axios.get(url).then(function (response) {
- console.log("封装的方法数据回来了");
- if (response.status === 200 && response.data.code === 200) {
- resolve(response.data);
- } else {
- reject(response.data);
- }
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
-
- post(url, data) {
- return new Promise((resolve, reject) => {
- axios.post(url, data).then(function (response) {
- if (response.status === 200) {
- resolve(response);
- } else {
- reject(response);
- }
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
- };
-
- export default request;
增加一个统一的请求loading效果
例如使用element ui的laoding。
先引入element ui中loading组件
- import {Loading} from 'element-ui'
- const loading = { // loading加载对象
- loadingInstance: null,
- // 打开加载
- open(loadtext) {
- if (this.loadingInstance === null) { // 如果实例 为空,则创建
- this.loadingInstance = Loading.service({
- text: loadtext, // '加载中...', // 加载图标下的文字
- spinner: 'el-icon-loading', // 加载图标
- background: 'rgba(0, 0, 0, 0.8)', // 背景色
- customClass: 'loading' // 自定义样式的类名
- })
- }
- },
- // 关闭加载
- close() {
- // 不为空时, 则关闭加载窗口
- if (this.loadingInstance !== null) {
- this.loadingInstance.close()
- }
- this.loadingInstance = null
- }
- }
然后在请求拦截中去打开,在结束拦截中去关闭以及错误的情况去关闭即可
- // 请求拦截器
- axios.interceptors.request.use((axiosconfig) => {
- loading.open()
- console.log("进入请求拦截器了")
- console.log(axiosconfig)
- return axiosconfig;
- },
- (err) => {
- loading.close() // 关闭加载窗口
- return Promise.reject(err);
- }
- );
-
- // 响应拦截器
- axios.interceptors.response.use(
- (response) => {
- console.log("统一响应了");
- loading.close() // 关闭加载窗口
- return response;
- },
- (err) => {
- loading.close() // 关闭加载窗口
- return Promise.reject(err);
- }
- );
-
- const request = {
- get(url, data) {
- // 判断有没有参数,有参数就把参数加上
- if (data) {
- url = url + "?" + qs.stringify(data);
- }
-
- return new Promise((resolve, reject) => {
- axios.get(url).then(function (response) {
- console.log("封装的方法数据回来了");
- if (response.status === 200 && response.data.code === 200) {
- resolve(response.data);
- } else {
- reject(response.data);
- }
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
-
- post(url, data) {
- return new Promise((resolve, reject) => {
- axios.post(url, data).then(function (response) {
- if (response.status === 200) {
- resolve(response);
- } else {
- reject(response);
- }
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
- };
-
- export default request;
如果想某些接口调用不用laoding效果,就可以这样实现
在请求拦截的时候不去开启loading,不然每个请求都会打开loading,而是给一个参数,有的情况才开启
- post(url, data, loadtext) {
- if (loadtext && loadtext.length > 0) {
- loading.open(loadtext); // 加载Loading
- }
-
- return new Promise((resolve, reject) => {
- axios.post(url, data).then(function (response) {
- if (response.status === 200) {
- resolve(response);
- } else {
- reject(response);
- }
- })
- .catch((e) => {
- reject(e);
- });
- });
- },
上面就判断了如果有传递loadtext就执行open方法打开loading,调用接口的时候如果需要loading就传递一个字符串过来就行
- this.$http.post("/api/v1/Home", { userName: "张三" },"数据请求中").then((res) => {
- console.log("post数据成功回来了")
- console.log(res)
- })
当然还有很多可以封装,根据实际的业务情况进行封装就行了
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)
饰心
跨域不是后端来处理嘛:app.UseCors();
人生若只如初见
跨域还可以使用qs啊
人生若只如初见
而且,用了好久发现vue使用 ajxa 要好些 自动解决跨域就是core 后台接收的时候 如果是post 就要 fromfrom 这个特性了
是伍尚金哇_v
前端整跨域用的代理(后端不处理得话)