nuxt axios接口配置及使用和跨域处理

4,807 阅读1分钟

如何发起跨域资源请求

[用于 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()
}

cookie使用参考文章

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>