https://zhuanlan.zhihu.com/p/340615580
示例: 为生成router.js代码写一个单元测试
import { Router } from '../tranform/vue/router';
import { PageParser } from '../index';
const babelParser = require('@babel/parser');
const generate = require('@babel/generator').default;
const traverse = require('@babel/traverse').default;
describe('测试router', () => {
const routerDsl = [{
pageid: 'form',
title: `form.name`,
pageName: 'form',
meta: {
icon: 'fin-icon-s-home',
breadcrumb: false,
},
children: [
{
pageid: 'detail',
title: `form.detail`,
pageName: 'detail',
meta: {
icon: 'fin-icon-s-home',
breadcrumb: false,
},
},
],
}];
const pageDsl = {
fileName: 'index',
id: 'form',
shareData: [],
action: {},
components: [],
apiConfigs: [],
apis: [],
};
const pageParser = new PageParser(pageDsl)
const router = new Router(pageParser, routerDsl);
test('test generateRouterCode', () => {
const res = router.toString();
console.log('res', res);
console.log('success');
})
})
生成router.js源码:
import { ct } from '../../utils/createType';
import { PageParser } from '../../parser/page';
import generate from '@babel/generator';
const babelParser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
export class Router {
private parser: any;
private routerConf: any;
private baseCode: string = `
import basicLayout from '@/layouts/basic-layout';
const sort = 1;
const routers = [];
export default routers;
`;
constructor(parser: any, routerConf: any) {
this.parser = parser;
this.routerConf = routerConf;
}
private getRouterConfig() {
const curRouterConfig = this.routerConf.find((item) => item.pageid === this.parser.dsl.id);
if (curRouterConfig) {
return curRouterConfig;
}
const routerName: string = this.parser.dsl.fileName || 'index';
const moduleName: string = this.parser.dsl.id || 'module';
return {
title: routerName,
pageid: moduleName,
pageName: routerName,
meta: {
icon: 'fin-icon-s-home',
breadcrumb: false,
},
children: [],
}
}
private genChildConf(arr) {
const routerConfig = this.getRouterConfig();
const {
pageid: moduleName,
pageName: routerName,
} = routerConfig;
const childrenConf = [];
arr.forEach((item, index) => {
const {
pageid: childId=`${moduleName}${index}`,
pageName: childName=`${routerName}${index}`,
title:subTitle = `${routerName}${index}`,
meta={},
children:sub = [],
} = item;
meta.title = subTitle;
let path: string = '';
if (childId === moduleName) {
path = `/${moduleName}`;
} else {
path = `/${moduleName}/${childId}`;
}
const importStr = `/* webpackChunkName: ${moduleName} */ '../view/${childName}.vue'`;
childrenConf.push(
ct.objectExpression([
ct.objectProperty(ct.identifier('path'),ct._convert(path)),
ct.objectProperty(ct.identifier('component'),
ct.arrowFunctionExpression(
[],
ct.callExpression(
ct.identifier('import'),
[ct.identifier(importStr)]
)
)
),
ct.objectProperty(ct.identifier('meta'),ct._convert(meta)),
ct.objectProperty(ct.identifier('children'), this.genChildConf(sub)),
])
);
});
return ct.arrayExpression(childrenConf);
}
private generateRouterArr() {
const routerConfig = this.getRouterConfig();
const {
title = '' ,
pageid: moduleName,
pageName: routerName,
meta = {},
} = routerConfig;
const path = `/${moduleName}`;
meta.title = title;
const children = [{
title,
pageid: moduleName,
pageName: routerName,
meta,
children: routerConfig.children,
}];
return ct.variableDeclaration('const', [
ct.variableDeclarator(
ct.identifier('routers'),
ct.arrayExpression([
ct.objectExpression([
ct.objectProperty(ct.identifier('sort'),ct.identifier('sort')),
ct.objectProperty(ct.identifier('path'),ct._convert(path)),
ct.objectProperty(ct.identifier('component'),ct.identifier('basicLayout')),
ct.objectProperty(ct.identifier('meta'),ct._convert(meta)),
ct.objectProperty(ct.identifier('children'), this.genChildConf(children)),
])
])
)
]
);
}
private generateRouterCode() {
const routerConfig = this.getRouterConfig();
const {
pageid: moduleName,
sort = 1,
} = routerConfig;
const ast = babelParser.parse(this.baseCode, { sourceType: 'module' });
const routerArr = this.generateRouterArr();
const astVistor = {
enter(path) {
if (ct.isVariableDeclaration(path)) {
switch (path.node.declarations[0].id.name) {
case 'sort':
path.node.declarations[0].init.value = sort;
break;
case 'routers':
path.node.declarations = routerArr.declarations;
break;
default: break;
}
}
},
}
traverse(ast, astVistor);
const newScript = generate(ast, {
jsescOption: { "minimal" : true }
}, this.baseCode);
return newScript.code;
}
public toString() {
if (this.parser instanceof PageParser) {
return this.generateRouterCode();
}
return '';
}
}
|