基于vuex动态添加接口(含axios的封装)

当项目过大时会存在很多接口,而且不同人写不同的接口很不方便管理,这里可以定义在json文件里面定义接口,然后通过模板生成相应的文件,这样会方便管理和阅读,在根目录定义一个coder文件夹,定义一个schema.json文件,先来看看定义的接口json文件如下:

{
    "doc": {
        "models": {
            "sooKey": [
                {
                    "title": "菜单",
                    "path": "/menu/getMenu",
                    "methods": false,
                    "name": "getMenu",
                    "state": "getMenu",
                    "httpMethod": "post"
                },
                {
                    "title": "哎呦不错呦12",
                    "path": "xtztc/info/key12",
                    "methods": false,
                    "name": "getScriptPeple",
                    "state": "getScriptPeple",
                    "httpMethod": "post"
                }
            ],
            "myTest": [
                {
                    "title": "测试",
                    "path": "/menu/getTitle",
                    "methods": false,
                    "name": "getTitle",
                    "state": "getTitle",
                    "httpMethod": "post"
                }
            ]
        }
    }
}

上面定义的文件中title为描述接口的描述,path为接口路径,name定义接口的方法,httpMethod为请求的方法,每个数组相当于一个模块下的接口,这里以post为演示,在coder文件下定义一个index.js文件,创建一个templates文件夹,在templates文件夹下创建两个文件分别是:types.js和store.js如下:

image.png

先看看index.js文件

const fs = require('fs')
const path = require('path')
// 引入遍历插件
const _ = require('lodash')
// const rm = require('rimraf')

// 引入接口文档
const SCHEMA = require('./schema.json')
const beautify = require('js-beautify').js_beautify
// 导入生产types模板
const typesRender = require('./templates/types')

//导入生成store的模板
const storeRender = require('./templates/store')

// 配置文件
const config = {
    // 生成store文件路径
    outStorePath: '../src/store/coder/',
    // 生成store配置文件路径
    outStoreType: '../src/store/',
}
// const MODELS = parseSchemas(SCHEMA.doc.models || {})
// json文件赋值
const MODELS = SCHEMA.doc.models || {};

/**
 * 创建文件
 * @param path
 * @param fileName
 * @param content
 */
function writeFile (path, fileName, content) {
  if (!fs.existsSync(path)) {
    fs.mkdirSync(path)
  }
  fs.writeFileSync(path + toKebabCase(fileName) + '.js', content, {encoding: 'utf8'})
}
// 大小写转换
function toUpperCase (name) {
  return name.toUpperCase()
}

/**
 * Foo Bar | --foo-bar | __foo_bar__ => fooBar
 * @param name
 */
function toCamelCase (name) {
  return _.camelCase(name)
}

/**
 * Foo Bar | fooBar | --foo-bar => foo_bar
 * @param name
 */
function toSnakeCase (name) {
  return _.snakeCase(name)
}

/**
 * fooBar => foo-bar
 * @param name
 */
function toKebabCase (name) {
  return _.kebabCase(name)
}

function toUpperSnakeCaseName (name) {
  return toUpperCase(toSnakeCase(name))
}

/**
 * 格式化js代码
 * @param content
 * @returns {*}
 */
function beautifyJs (content) {
  content = content.replace(/(\r\n|\n)\s*/g, '\n')
    .replace(/\(\n/g, '(')
    .replace(/,\n/g, ',')
    .replace(/\/\*\*/g, '\n/**')
    .replace(/\n\/\//g, '\n\n//')
  return beautify(content, {
    indent_with_tabs: false,
    indent_size: 2,
    jslint_happy: true,
    end_with_newline: true,
    space_after_anon_function: true
  })
}
/**
 * 生成store文件
 */
function writeStore () {
  // 定义types模板的数据
  let types = {}
  //定义modules.js的数据和modules.js导出的字段
  let modules = [], extendsArray = []
  // 遍历json文件
  _.each(MODELS, function (model, name) {
     modules.push(`import ${name} from './coder/${ toKebabCase(name)}'`)
     extendsArray.push(name)
      let importTypeArray = [],
      customStateArray = [],
      items = []
     types[name] = []
     _.each(model, function (item) {
        types[name].push({
          name: toUpperSnakeCaseName(item.name)
        })
        importTypeArray.push(toUpperSnakeCaseName(item.name))
        customStateArray.push(item.state)
        items.push({
          NAME: toUpperSnakeCaseName(item.name),
          name: toCamelCase(item.name),
          state: item.state,
          url: item.path,
          httpMethod: item.httpMethod,
          ajaxParam: 'data'
        })
     })
     // 定义生成文件的路径
     const outPath = path.join(__dirname, config.outStorePath)
     console.log(items, 'itemsitemsitems');
     // 生成store模板文件并传值
     writeFile(outPath, name, beautifyJs(storeRender({
       name: name,
       kebabCaseName: toKebabCase(name),
       importTypeArray: importTypeArray,
       customStateArray: customStateArray,
       items: items
     })))
  });
   // 定义生成文件的路径
  const outStore = path.join(__dirname, config.outStoreType)
  // 生成types模板文件并传值
  writeFile(outStore, 'types', beautifyJs(typesRender({types: types})))
  modules.push(`export default {${extendsArray.join(', ')}}`)
   // 生成modules模板文件并传值
  writeFile(outStore, 'modules', modules.join('\n') + '\n')
}
function init() {
    // 初始化
    // console.log(SCHEMA, 'asd');
    console.log('开始生成代码.....')
    writeStore();
    console.log('代码构建完成.....')
}
init()

然后是templates下的types.js文件和store.js文件

// types.js文件
const _ = require('lodash')
module.exports = _.template(`
<%_.each(types, function(items, name){%>
// <%=name%>
  <%_.each(items, function(item){%>
     export const <%=item.name%> = '<%=item.name%>'
  <%})%>
<%})%>
`)

// store.js文件
const _ = require('lodash')
module.exports = _.template(`
/*! build time: <%=new Date().toLocaleString()%> */
// <%=importTypeArray.join(', ')%>
import { <%=importTypeArray.join(', ')%> } from '../types'
import axios from "axios"
// store module
export default {
  actions: {
    <%_.each(items, function(item, i){%>
      <%if(i>0){%>,<%}%>  
      <%if(item.httpMethod == 'post'){%>
        [<%=item.NAME%>]({commit}, 
          <%_.each(item.params, function(param){%>
             <%=param%>,
          <%})%>
          <%=item.ajaxParam%>
          ={}) {
            return new Promise(function(resolve, reject){
              axios.post('<%=item.url%>',<%=item.ajaxParam%>).then(data=>{
                resolve(data)
              })
            });
          }
      <%}%>
    <%})%>
  }
}
`)

然后就是运行index.js文件,在package.json文件的scripts下添加一行"coder": "node coder/index.js"如下:

image.png

然后就是运行npm run coder,运行后会在src的store下types.js和modules.js文件,以及store文件夹下的code文件夹下的几个文件,文件个数和json下的数组个数相关,文件名称以json文件里面的name属性相关,具体代码可以看index.js,代码结构如下:

image.png

相关代码如下:

//soo-key.js文件,这里用到了vuex的action和modules
/*! build time: 2019-1-8 16:20:44 */

// GET_MENU, GET_SCRIPT_PEPLE
import {
  GET_MENU,
  GET_SCRIPT_PEPLE
} from '../types'
import axios from "axios"

// store module
export default {
  actions: {
    [GET_MENU]({
        commit
      },
      data = {}) {
      return new Promise(function (resolve, reject) {
        axios.post('/menu/getMenu', data).then(data => {
          resolve(data)
        })
      });
    },
    [GET_SCRIPT_PEPLE]({
        commit
      },
      data = {}) {
      return new Promise(function (resolve, reject) {
        axios.post('xtztc/info/key12', data).then(data => {
          resolve(data)
        })
      });
    }
  }
}

types.js文件
// sooKey
export const GET_MENU = 'GET_MENU'
export const GET_SCRIPT_PEPLE = 'GET_SCRIPT_PEPLE'

// myTest
export const GET_TITLE = 'GET_TITLE'

modules.js文件
import sooKey from './coder/soo-key'
import myTest from './coder/my-test'
export default {sooKey, myTest}

然后就是src下的store.js文件,也就是引入modules

import Vue from 'vue';
import Vuex from 'vuex'
// 引入modules文件
import modules from './modules'
import usually from './usually'
import getters from './getters'
Vue.use(Vuex);
export default new Vuex.Store({
    modules: {
       ...modules,
       usually
    },
    getters: {
       ...getters
    }
})

使用方法,在相应组件下引入import {GET_MENU} from "../../store/types";

this.$store.dispatch(GET_MENU, {asd:10}).then((res)=>{
         console.log(res, 'resresresres');
         this.menuList = res.data.msg;  
         // console.log(this.menuList, 'this.menuListthis.menuListthis.menuList');
      });

总结:以后不管是谁只要添加接口,只要在schema.json文件下添加相应的接口,然后直接运行npm run coder就可以自动生成相应文件,然后像上面一样调用就可以了

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

推荐阅读更多精彩内容