1. 前言
1.1 环境
- 操作系统: macOS 11.5.2
- 浏览器: Chrome 94.0.4606.81
-
1.2 阅读该文章可以get以下知识点
-
2. 开始
2.1 如何创建新组件
make new xxx
运行上面的命令会创建响应的资源文件
packages/xxx
- test/unit/specs/xxx.spec.js
- types/element-ui.d.ts
2.2 Makefile
```makefile .PHONY: dist test default: help
install: npm install
new:
这里会执行 build/bin/new.js下面的文件
node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS))
help:
@echo “ \033[35mmake\033[0m \033[1m命令使用说明\033[0m”
@echo “ \033[35mmake install\033[0m\t\033[0m\t\033[0m\t\033[0m\t—- 安装依赖”
@echo “ \033[35mmake new
挺有意思的写法,直接通过make new再去执行脚本<br />$(filter-out $@,$(MAKECMDGOALS))这段代码是将参数传入到new.js脚本中
1. $@
1. 会返回自身,例如 这里的new:,会返回new
2. $(MAKECMDGOALS)
1. 返回所有的参数,例如 make new xxx,会返回 new xx
3. filter-out反过滤函数
1. 有两个参数,第一个参数是匹配的字符串,第二个参数是需要处理的字符串
2. 过滤掉所有匹配的字符串,保留不匹配的,例如; make new xxx, 返回xxx,过滤掉了new
<a name="ezz5E"></a>
## 2.3 new.js
```javascript
'use strict';
console.log();
process.on('exit', () => {
console.log();
});
// 默认0和1是node环境变量和当前运行文件,第三个就是组件名
if (!process.argv[2]) {
console.error('[组件名]必填 - Please enter new component name');
process.exit(1);
}
const path = require('path');
const fs = require('fs');
// 文件存储
const fileSave = require('file-save');
// 驼峰转化
const uppercamelcase = require('uppercamelcase');
// 组件吗
const componentname = process.argv[2];
// 如果有中文名,传入第四个参数,没有的话,直接去组件吗
const chineseName = process.argv[3] || componentname;
// 转化成大驼峰
const ComponentName = uppercamelcase(componentname);
// 获取packages的路径
const PackagePath = path.resolve(__dirname, '../../packages', componentname);
// 文件名和模板语法
const Files = [
{
filename: 'index.js',
content: `import ${ComponentName} from './src/main';
/* istanbul ignore next */
${ComponentName}.install = function(Vue) {
Vue.component(${ComponentName}.name, ${ComponentName});
};
export default ${ComponentName};`
},
{
filename: 'src/main.vue',
content: `<template>
<div class="el-${componentname}"></div>
</template>
<script>
export default {
name: 'El${ComponentName}'
};
</script>`
},
{
filename: path.join('../../examples/docs/zh-CN', `${componentname}.md`),
content: `## ${ComponentName} ${chineseName}`
},
{
filename: path.join('../../examples/docs/en-US', `${componentname}.md`),
content: `## ${ComponentName}`
},
{
filename: path.join('../../examples/docs/es', `${componentname}.md`),
content: `## ${ComponentName}`
},
{
filename: path.join('../../examples/docs/fr-FR', `${componentname}.md`),
content: `## ${ComponentName}`
},
{
filename: path.join('../../test/unit/specs', `${componentname}.spec.js`),
content: `import { createTest, destroyVM } from '../util';
import ${ComponentName} from 'packages/${componentname}';
describe('${ComponentName}', () => {
let vm;
afterEach(() => {
destroyVM(vm);
});
it('create', () => {
vm = createTest(${ComponentName}, true);
expect(vm.$el).to.exist;
});
});
`
},
{
filename: path.join('../../packages/theme-chalk/src', `${componentname}.scss`),
content: `@import "mixins/mixins";
@import "common/var";
@include b(${componentname}) {
}`
},
{
filename: path.join('../../types', `${componentname}.d.ts`),
content: `import { ElementUIComponent } from './component'
/** ${ComponentName} Component */
export declare class El${ComponentName} extends ElementUIComponent {
}`
}
];
// 添加到 components.json
const componentsFile = require('../../components.json');
if (componentsFile[componentname]) {
console.error(`${componentname} 已存在.`);
process.exit(1);
}
componentsFile[componentname] = `./packages/${componentname}/index.js`;
// 存储新的json
fileSave(path.join(__dirname, '../../components.json'))
.write(JSON.stringify(componentsFile, null, ' '), 'utf8')
.end('\n');
// 添加到 index.scss
const sassPath = path.join(__dirname, '../../packages/theme-chalk/src/index.scss');
const sassImportText = `${fs.readFileSync(sassPath)}@import "./${componentname}.scss";`;
fileSave(sassPath)
.write(sassImportText, 'utf8')
.end('\n');
// 添加到 element-ui.d.ts
const elementTsPath = path.join(__dirname, '../../types/element-ui.d.ts');
let elementTsText = `${fs.readFileSync(elementTsPath)}
/** ${ComponentName} Component */
export class ${ComponentName} extends El${ComponentName} {}`;
const index = elementTsText.indexOf('export') - 1;
const importString = `import { El${ComponentName} } from './${componentname}'`;
elementTsText = elementTsText.slice(0, index) + importString + '\n' + elementTsText.slice(index);
fileSave(elementTsPath)
.write(elementTsText, 'utf8')
.end('\n');
// 创建 package
Files.forEach(file => {
fileSave(path.join(PackagePath, file.filename))
.write(file.content, 'utf8')
.end('\n');
});
// 添加到 nav.config.json
const navConfigFile = require('../../examples/nav.config.json');
Object.keys(navConfigFile).forEach(lang => {
let groups = navConfigFile[lang][4].groups;
groups[groups.length - 1].list.push({
path: `/${componentname}`,
title: lang === 'zh-CN' && componentname !== chineseName
? `${ComponentName} ${chineseName}`
: ComponentName
});
});
fileSave(path.join(__dirname, '../../examples/nav.config.json'))
.write(JSON.stringify(navConfigFile, null, ' '), 'utf8')
.end('\n');
console.log('DONE!');
3. 总结
- 熟悉了一些Makefile的语法
- 通过Makefile的方式,去执行一些脚本,代码很简洁,如 make new, make help,不需要去写package.json scripts,减少了script的脚本,但是也有一定的理解成本,有些前端同学不懂Makefile,windows环境需要gcc环境
-
4. 参考文档
- https://www.npmjs.com/package/element-ui