Vue + webpack 项目配置化、接口请求统一管理

准备工作

需求由来: 当项目越来越大的时候提高项目运行编译速度、压缩代码体积、项目维护、bug修复......等等成为不得不考虑而且不得不做的问题。
又或者后面其他同事接手你的模块,或者改你的bug时避免人家看的眼痛以及心里千百句mamaipi...问候。
并且一个好的开发思路也能大大提高开发效率,以及检验自己。

进入正题:
在本地用 vue-cli 新建一个项目,这个步骤参照vue的官网。
这里展示一下我的项目架构目录 这次主要讲红字具体实现部分

1、项目地图

├── build                       // 项目build脚本
      ├── config                      // 项目配置目录
      ├── dist                        // 项目输出部署目录,执行 npm run build后生成
      ├── src                         // 生产目录
      │   ├── assets                  // 静态资源,包含图片等
      │   ├── components              // 项目公用组件,例如Header、Footer组件等
      │   ├── mock                    // 接口mock文件目录
      │       └── index.js            // mock接口集合文件
      │   ├── pages                   // 页面目录
      │   │   ├── Demo                // Demo模块,必须用大写开头
      │   │   │   ├── components      // Demo模块专用组件 组件建议全部首字母大写
      │   │   │   ├── style           // Demo模块专用css
      │   │   │   ├── services        // Demo模块服务,可以包含相应方法类
      │   │   │   ├── interface.js    // Demo模块接口结合文件
      │   │   │   └── index.vue       // Demo模块页面入口
      │   │   └── Other               // 其他页面目录
      │   ├── router                  // 路由配置文件,如果路由太多了,可以拆分
      │   ├── services                // 项目公用配置服务
      │   │   │   ├── ajax.js         // 所有接口请求公共配置   可以和 request.js 合并一起 不嫌代码太长的话
      │   │   │   ├── request.js      // (需求有则添加) 为所有接口设置公共请求头
      │   │   │   ├── prompt.js       // 全局的提示  例如:接口错误提示、保存成功提示、操作错误提示等等...
      │   │   │   ├── validate.js     // 全局表单校验具体封装可参照element-ui form表单模块
      │   ├── App.vue                 // 组件入口
      │   ├── config.js               // 项目配置文件  例如:权限校验,cookie设置、access_token获取等等...
      │   ├── interface.js            // 项目公共接口文件
      │   └── main.js                 // Webpack 预编译主入口
      ├── style                       // 项目公用style
      ├── static                      // 静态文件目录,保留
      │   └── i18n                    // 国际化目录,每一个目录为一种语言
      │       ├── zh                  // 中文目录
      │       │   └── index.json      // 配置文件
      │       └── en                  // 英文目录
      ├── index.html                  // 项目入口文件,一般不用改动
      ├── package.json                // 项目配置
      ├── README.md                   // 项目说明
      ├── CHANGE_LOG.md               // 项目更新历史文档
      └── test                        // 测试目录

2、services/aiax.js文件

/**
 * ajax 模块,可以将 axios 替换成 $.ajax 等
 */
import axios from 'axios';
import globalConfig from '../config'
import { Notification } from 'element-ui'

// 注: 具体设置具体判断 根据公司项目需求 以及 接口需求   现在以我公司为例

const init = function () {
  // 添加 axios 请求拦截器为所有请求加上前缀 、 access_token  (我公司所有接口都比要有 access_token才能访问)
  // 有对 axios 不是很了解的 可以看看 axios 官方文档  https://www.kancloud.cn/yunye/axios/234845
  axios.interceptors.request.use(function (config) {
    // 为所有接口加上前缀 例 https://www.kancloud.cn/yunye/axios/234845 前缀为 https://www.kancloud.cn
    // 因为相同环境下的所有接口前缀肯定是一样的 window.localStorage.gatewayDomain 为前缀域名  倘若后面更改域名之类的  只需改一个地方就行了 就不用说每个调接口的地方都去改  维护便捷
    // 若想了解分环境打包以及分环境设置 公共域名、前缀等  请看以往博文 https://www.cnblogs.com/ljx20180807/p/9456489.html
    config.url = window.localStorage.gatewayDomain + config.url
    
    // 登录时设置 cookies
    var cookies = globalConfig.getCookies()
    if (config.url.indexOf('?') < 0) {
      config.url += '?'
    }
    // 为所有接口加上 access_token
    config.url += ('access_token=' + cookies['access_token'])
    if (!config.data) config.data = {}
    return config;
  }, function (err) {
    // 错误处理
    return Promise.reject(err)
  })

  // 添加 axios 响应拦截器
  axios.interceptors.response.use(function (response) {

    // 这里是当接口请求服务器成功响应的情况   解构赋值出需要的数据
    const {status, data} = response;

    if (status === 200) {
      // 如果不出现错误,直接向回调函数内输出 data  状态200
      if (data.error === 'SUCCESS') {
        // 成功不用提示
        return data
      } else {
        // 若出现错误则弹窗错误提示
        if (data.message) {
          Notification({
            title: '错误',
            message: data.message,
            type: 'error',
            customClass: 'el-error-msg',
            duration: 2000
          })
        }
        return data
      }
    } else {
      return response;
    }
  }, function (error) {
    // 这里是当接口请求失败的情况 (例如服务器没响应、后台代码问题之类的)  (具体的响应判断根据你后台返回状态码结构)
    const {response} = error;

    // 这里处理错误的 http code
    if (!response || response.status === 404) {
      if (!response) {  // access_token 失效的情况 弹窗提示
        Notification({
          title: '错误',
          message: 'access_token已失效请重新登录',
          type: 'error',
          customClass: 'el-error-msg',
          duration: 1500,
          onClose() {
            window.location.href = window.localStorage.loginUrl  // 自动跳转返回登录页重新获取access_token
          }
        })
      } else {
        // 这是请求url不对的情况
        console.log('404 error %o' + error);
      }
    }
    // Do something with response error 对响应错误做点什么
    return Promise.reject(error.message);
  });
};

export default {
  init
}

3、services/prompt.js文件

const init = function () {
  const _this = this;
  // 建议为了方便使用,这里可以包装window.Alert  具体怎么使用往下看
  window.Alert = function (msg, duration = 3000) {
    // 错误提示
    _this.$notify({
      title: '错误',
      message: msg,
      type: 'error',
      customClass: 'el-error-msg',
      duration
    });
  }
 // 成功提示
  window.Tips = function (msg, duration = 3000) {
    _this.$notify({
      title: '成功',
      message: msg,
      type: 'success',
      duration
    });
  }
 // 警告提示
  window.Warning = function (msg, duration = 3000) {
    _this.$notify({
      title: '警告',
      message: msg,
      type: 'warning',
      duration
    });
  }

  // 全局延时器
  window.SetTimeout = function (path, queryObject) {
    setTimeout(_ => {
      _this.$router.push({
        path: path,
        query: queryObject
      });
    }, 500)
  }
};

export default {
  init
}

3、page/Demo/interface.js文件 (pc端不建议用vuex 具体看需求吧 vuex管理版本 往下看)

import axios from 'axios';

const ajax = {
  // 获取影像件上传列表
  GET_IMAGE_LIST: 'images?'
};
// 提取公共部分
const API_PATH_PRE_FIX = 'apply/v1/'; 

// 增加接口模块前缀
let INTERFACE = {};
for (let key in ajax) {
  INTERFACE[key] = API_PATH_PRE_FIX + ajax[key];
}

/**
 * 方式1: 多参数情况  获取列表
 * @param data 参数
 * @returns {*}
 */
function getImageList(data) {
  return axios.get(INTERFACE.GET_IMAGE_LIST, {
    params: data
  }).catch(function (error) {
    window.Alert(error);
  });
}

/**
 * 方式2: es6模板语法  获取基本信息
 * @param data 参数
 * @returns {*}
 */
function getContrantInfo(API_PATH_PRE_FIX, agreementId) {
  return axios.get(`${API_PATH_PRE_FIX}/middle/agreement/basic?agreementId=${agreementId}&`).catch(function (error) {
    window.Alert(error);
  });
}
export default {
  getImageList,
  getContrantInfo,
};

4、page/Demo/index.vue文件

<script>
// 引入上面的接口文件
import INTERFACE from './interface'
export default {
  data() {
    return {
      imageList: [],
      deleteList: []
    }
  },
  created() {
    // 获取列表 (调用封装好的请求)
    INTERFACE.getImageList().then(data => {
      if (data && data.data) this.imageList = data.data
    })
  },
  methods: {
    // 确认删除
    handleDelete() {
      INTERFACE.deleteAgreement(this.deleteList).then(data => {
        // 操作成功提示 (上面定义好的全局提示)
        window.Tips('删除成功!')
      })
    }
  }
}
</script>

5、src/main.js文件

import Vue from 'vue'
import ElementUI from 'element-ui'
import App from './App'
import ajax from '@/services/ajax'

// axios 统一配置
ajax.init()

// 全局变量
indow.localStorage.gatewayDomain = 'https://dev-api.cn/'
window.localStorage.defaultLanguage = 'ZH_CN'

6、src/App.vue文件

<script>
import prompt from '@/services/prompt'
export default {
  name: 'app',
  mounted() {
    // 全局错误初始化
    prompt.init.call(this)
  }
}
</script>

以上就是pc端的项目配置化、请求统一管理内容了。有疑问的地方留言看到后会第一时间回复,或可改进的地方欢迎指导, 下面介绍vuex管理版本。


7、移动端结合Vuex 统一管理请求 stroe/actions.js文件

import Vue from 'vue'

// 全局域名
const apiUrlBase = window.apiUrlBase

const API_URL = {
  GET_APPLICENT: `${apiUrlBase}/app/v1/apply/dictionaries`
}

const actions = {
   /**
 * 获取投保人数据字典
 */
actions.getApplicent = ({ state }) => {
  return new Promise((resolve, reject) => {
    Vue.http.get(`${API_URL.GET_APPLICENT}?access_token=${state.accessToken}`).then((ret) => {
        resolve(ret.body)
      }).catch((err) => {
        reject(err)
      })
    })
  }
}

export default actions

8、.vue文件里调用

this.$store.dispatch(`${storeName}/getApplicent`)
      .then((data) => {
        console.log(data)
      })

这就可以啦。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容

  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,154评论 0 1
  • F7+Vue+WebPack移动端单页应用脚手架 1 简介 F7-VUE-WEBPACK-SCAFFOLD,是一个...
    bluexiii阅读 5,763评论 0 8
  • 来源:http://www.cnblogs.com/opendigg/p/6513510.html UI组件 el...
    YU_XI阅读 2,848评论 0 26
  • 最惬意的生活,莫过于做自己喜欢做的事,生活成自己喜欢的样子。我想我自己莫过于在文字里取暖,在文字中找到自己的影子。...
    落叶兰秋阅读 1,328评论 6 46
  • :为什么学历不值钱,而学区房值钱? :学历已无预期,学区房有无限预期。 总结:“保状态,稳预期”是营销的终极目标
    马唐阅读 112评论 0 0