基于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就可以自动生成相应文件,然后像上面一样调用就可以了

你可能感兴趣的:(基于vuex动态添加接口(含axios的封装))