Vue中axios二次封装,环境变量配置,代理,打包注意的地方

Vue中环境变量配置及axios二次封装

前一阵着急做一个vue项目,中间有很多需要注意的地方,今天简单做个总结

项目主要流程

一. vue项目脚手架正常构建代码,开发,属于常规操作,其中路由是核心内容

import Vue from 'vue'
import VueRouter from 'vue-router'
// ----相关页面----
import Layout from '@layout/layout.vue' // 是包含菜单标题的页面布局(里面有一个router-view)
import MonitorTask from '@pages/monitor-task/monitorTask.vue' //监测任务管理
import StreamList from '@pages/stream-inspect/streamList.vue' //数据监测列表

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/layout/stream/monitor-task' //页面重定向
  },
  {
    "path": "/layout",
    "name": "layout",
    "component": Layout,
    "children": [
      {
        "path": "stream/monitor-task",
        "name": "monitortask",
        "component": MonitorTask,
        "meta": {
          "title": "监测任务管理"
        }
      },
      {
        "path": "stream/data-list",
        "name": "streamList",
        "component": StreamList,
        "meta": {
          "title": "直播数据监测列表"
        }
      }
    ]
  }
]

const router = new VueRouter({
  base: process.env.BASE_URL,
  routes: routes
})

export default router
<template lang="pug">
a-layout
  a-layout(style="position:relative;overflow:hidden;")
    a-layout-content(style="background-color:#f0f2f5;")
    	//动态切换的页面
      router-view
</template>

二. 请求数据接口,这里就涉及到axios二次封装
每一个项目都会有一个request.js文件,专门用来处理请求接口

import axios from 'axios'
import qs from 'qs'
// axios封装 请求的实例
const instance = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})
// 前端请求
instance.interceptors.request.use(config => {
  // 一般这里会加个请求头 token 或者authoration,本次暂不加
  return config
}, error => {
  return Promise.reject(error)
})
// 后端响应给前端
instance.interceptors.response.use(response => {
  // 返回类型为blob文件时直接返回response.data
  if (response.config.responseType === 'blob') {
    const filename = response.headers['content-disposition'].split(';')[1].split('=')[1]
    const [fileExt] = filename.split('.').slice(-1)
    return {
      fileExt,
      filename,
      blob: response.data
    }
  }
  // 后端返回的文件流 excel等文件处理
  if (response.headers['content-type'] === 'application/octet-stream' || response.headers['content-type'] === 'application/vnd.ms-excel') {
    return response
  }

  return response.data
}, error => {
  // 2xx以外的状态码进入这里
  return Promise.reject(error)
})

// 封装的公共接口请求方法,注意一定是instance实例,
//若公共的请求方法写到另外一个单独的文件里,那需要把这个instance实例暴露出去,如:export default instance ,在单独的文件里引入暴露的实例,如: import {get, post...} from './request.js'
// 如果都在一个文件里面,那不需要暴露这个instance实例了,就像下面这样写
export default {
  get (url, params) {
    return instance({
      method: 'GET',
      url,
      params
    })
  },

  getFile (url, params){
    return instance({
      method: 'GET',
      url,
      params,
      responseType: 'blob',
      headers:{
        'Content-Type': 'application/json'
      }
    })
  },

  getPDF (url, params) {
    return instance({
      method: 'GET',
      url,
      params,
      responseType: 'blob'
    })
  },

  post (url, params) {
    return  instance({
      method: 'POST',
      url,
      data: qs.stringify(params)
    })
  },
  // 线索编辑上传文件
  postFile (url, params) {
    const formData = new FormData()
    formData.append('clue_id', params.clue_id)
    for (let i = 0; i < params.operate_arr.length; i++) {
      formData.append(`operate_arr[${i}][first_operate]`, params.operate_arr[i].first_operate !== null ? params.operate_arr[i].first_operate : '')
      formData.append(`operate_arr[${i}][second_operate]`, params.operate_arr[i].second_operate !== null ? params.operate_arr[i].second_operate : '')
      for (let j = 0; j < params.operate_arr[i].position.length; j++) {
        formData.append(`operate_arr[${i}][position][${j}]`, params.operate_arr[i].position[j])
      }
      formData.append(`operate_arr[${i}][operate_content]`, params.operate_arr[i].operate_content !== null ? params.operate_arr[i].operate_content : '')
      formData.append(`operate_arr[${i}][case_num]`, params.operate_arr[i].case_num !== null ? params.operate_arr[i].case_num : '')
      if (params.operate_arr[i].file.length > 0) {
        for (let j = 0; j < params.operate_arr[i].file.length; j++) {
          formData.append(`operate_arr[${i}][file][${j}]`, params.operate_arr[i].file[j])
        }
      }
      // formData.append(`operate_arr[${i}][file]`, params.operate_arr[i].file.length > 0 ? params.operate_arr[i].file[0] : '')
    }
    return instance({
      method: 'POST',
      url,
      data: formData
    })
  },

  postNoStringfy (url, params) {
    return instance({
      method: 'POST',
      url,
      data: params
    })
  },

  postFileCommon (url, params) {
    const formData = new FormData()
    Object.keys(params).forEach(key => {
      if (Array.isArray(params[key])) {
        params[key].forEach(item => {
          formData.append(`${key}[]`, item)
        })
      } else {
        formData.append(key, params[key])
      }
    })
    return instance({
      method: 'POST',
      url,
      data: formData
    })
  }
}

三、在业务api接口,我这里举例业务api:monitor-task.js

// 引入一个实例名称axios(名称随便) 调用里面的封装方法 如:axios.get
import axios from '../request'
// 监测任务管理列表
export function getStreamListApi (option) {
    const api = '/monitor-task/stream/task-list'
    return axios.get(api, option)
}
// 监测任务管理-新增
export function setAddTaskApi (option) {
    const api = '/monitor-task/stream/add-task'
    return axios.post(api, option)
}

四、业务里去用api接口

import { getStreamListApi, setAddTaskApi} from '@api/monitor-task/monitor-task.js'

async fetchList () {
   this.list = []
   this.paginationItem.total = 0
   let param = {
     ...this.queryParam,
     pn: this.paginationItem.current,
     ps: this.paginationItem.pageSize
   }
   const res = await getStreamListApi(param)
   if (res.code === 0) {
     this.list = res.data.list
     this.paginationItem.total = res.data.rows
   }
 },

环境变量配置

目的:是为了根据不同的环境发布不同的代码

"scripts": {
    "serve": "vue-cli-service serve", // 对应开发环境
    "oldBuild": "vue-cli-service build", // 对应线上环境
    "build": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js build",// 对应线上环境
    "lint": "vue-cli-service lint",
    "postinstall": "patch-package"
  },

项目根目录下这两个文件就是根据命令自动执行的npm run serve,npm run build 开发和测试环境配置
在这里插入图片描述

// 开发环境的配置
ENV = 'development'
VUE_APP_BASE_API = 'http://localhost:8080/'

// 线上环境的配置
ENV = 'production'
VUE_APP_BASE_API = 'http://192.168.1.214/'

注意1: 打包之后请求的地址链接就是线上链接(接口服务) 比如http://xxx.xx.x.xx/live-monitor/stream/clue-list

注意2: request.js 请求的实例 process.env.VUE_APP_BASE_API可以获取到不同环境的请求接口地址

const instance = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

代理 proxy

在本地开发环境,想让接口走通,是可以用代理的方式,注意:到线上环境根本不走这个,和这个一点关系没有,走的就是axios封装实例 VUE_APP_BASE_API

const trunkProxy = {
  target: 'http://10.202.xxx.xxx/',
  changeOrigin: true,
  headers: {
    Referer: 'xxx_yyy.com/',
    Host: 'xxx_yyy.com'
  }
}
const proxyConfig = trunkProxy
// 此处是代理 网关,每次请求这些首个单词,就代理到测试环境的接口地址10.201.xxx.xxx
const apis = 'user path ad role org module menu trad dic notice index knowledge outdoor site live-monitor detail-analysis monitor-task'
const proxy = apis.split(' ').reduce((conf, api) => {
  conf[`/${api}/`] = proxyConfig
  return conf
}, {})

module.exports = {
  devServer: {
    disableHostCheck: true,
    proxy
  }
}

打包 vue.config.js

1、文件单独打包,执行npm run build 比如打包后生成dist文件,里面要分别有js,css,img文件等

const path = require('path')
const Webpack4QCDNPlugin = require('@q/webpack4-qcdn-plugin')
module.exports = {
  publicPath: './',
  assetsDir: 'static',
  productionSourceMap: false, //反编译
  configureWebpack: config => {
    Object.assign(config, {
      resolve: {
        alias: {
          '@components': path.resolve(__dirname, 'src/components/'),
          '@pages': path.resolve(__dirname, 'src/pages/'),
          '@layout': path.resolve(__dirname, 'src/layout/'),
          '@styles': path.resolve(__dirname, 'src/styles/'),
          '@api': path.resolve(__dirname, 'src/api/'),
          '@store': path.resolve(__dirname, 'src/store/'),
          '@js': path.resolve(__dirname, 'src/scripts/'),
          '@images': path.resolve(__dirname, 'src/assets/images/'),
          '@test': path.resolve(__dirname, 'src/test/'),
          '@utils': path.resolve(__dirname, 'src/utils/')
        }
      },
      externals: {
        vue: 'Vue',
        'vue-router': 'VueRouter',
        vuex: 'Vuex',
        axios: 'axios'
      }
    })
    // 此处是打包成一个文件 index.html里
    // if (env === 'production') {
    //   config.plugins.push(
    //     new Webpack4QCDNPlugin({
    //       // qcdn 配置,详见 http://qnpm.qiwoo.org/package/@q/qcdn
    //       qcdnOption: {
    //         image: {
    //           https: true,
    //           domains: ['p1.ssl.qhimg.com']
    //         },
    //         static: {
    //           https: true,
    //           domains: ['s0.qhres2.com', 's2.ssl.qhres2.com']
    //         }
    //       },
    //       concurrency: 5,
    //       maxRetryCount: 5
    //       // keepLocalFiles: true
    //       // 其他配置项见 https://github.com/AngusFu/webpack4-cdn-plugin
    //     })
    //   )
    //   config.mode = 'production'
    // }
  },
  transpileDependencies: ['ant-design-vue'],
  lintOnSave: false,
  runtimeCompiler: true,
  css: {
    loaderOptions: {
      less: {
        javascriptEnabled: true
      }
    }
  }
}

2、打包成一个文件 index.html里 就是上方注解的部分, 同时对应的public文件目录下的index页面用的外部链接 (下方注释的部分)打包成第一种方式就是下方未注解的部分

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta vue-app-version="<%=VUE_APP_VERSION %>">
  <link rel="icon" type="image/png" href="./icon.png">
  <title>xxx平台</title>
  <link href="./font-awesome.min.css"></link>
  <!-- <link href="//lib.baomitu.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> -->
</head>

<body>
  <div id="app"></div>
  <script src="./js/vue.js"></script>
  <script src="./js/vue-router.min.js"></script>
  <script src="./js/vuex.min.js"></script>
  <script src="./js/axios.min.js"></script>
  <!-- <script src="//lib.baomitu.com/vue/2.6.10/vue.js"></script> -->
  <!-- <script src="//lib.baomitu.com/vue-router/3.1.3/vue-router.min.js"></script> -->
  <!-- <script src="//lib.baomitu.com/vuex/3.1.2/vuex.min.js"></script> -->
  <!-- <script src="//lib.baomitu.com/axios/0.18.0/axios.min.js"></script> -->
  <!-- <script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=853ca75f8f4366f584fc8c8fe607d9b1"></script> -->
</body>
</html>

至此,整个vue项目就可以从开发到发布串起来了,这是比较基础的地方,希望能帮助到有需要的小伙伴们~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue使用axios进行二次封装的步骤如下所示: 第一步,在项目的`apis`文件夹下创建一个`http.js`文件,用于封装axios的请求方法。在该文件,通过`export`将方法暴露出去,方便在所需页面进行调用。例如,可以创建一个获取用户列表信息的方法`get_users`: ```javascript import http from './index.js' export const get_users = (params) => { return http({ method: "GET", url: "users", params: params }) } ``` 第二步,设置基地址和拦截器。可以使用axios的`create`方法创建一个自定义的axios实例,并在其设置基地址和拦截器。例如: ```javascript import axios from 'axios' const request = axios.create({ baseURL: '基地址1', timeout: 5000 }) request.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config }, function (error) { // 对请求错误做些什么 return Promise.reject(error) }) request.interceptors.response.use(function (response) { // 对响应数据做点什么 return response.data }, function (error) { // 对响应错误做点什么 return Promise.reject(error) }) ``` 第三步,在页面引入`http.js`文件,并调用自己所配置好的请求方法。可以使用`import`语句引入`http.js`暴露的方法,然后在页面的方法使用`async`和`await`对请求方法进行异步请求,最终可以直接获取到请求的数据信息。例如: ```javascript import { get_users } from '../apis/http.js' export default { props: {}, data() { return {} }, created() { // 在钩子函数调用自定义的getUserList方法 this.getUserList() }, methods: { // 自定义方法调用get_users方法,通过async和await进行异步请求 async getUserList() { // 调用get_users方法并获取请求数据 let { data: res } = await get_users(params) // 在页面上渲染数据 // console.log(res) } }, components: {} } ``` 这样,在Vue就可以使用axios进行二次封装,并通过引入和调用自定义的请求方法来获取数据。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Vueaxios二次封装](https://blog.csdn.net/m0_63905956/article/details/125589282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [vueaxios二次封装](https://blog.csdn.net/qq_20623665/article/details/128243379)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值