持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
前言
平常大家开发每个页面骨架大致相似,每次开发新页面都要一步一步的配置,相当繁琐。有了Plop,就可以实现自动化了,Plop 旨在根据模板文件自动化创建组件,接下来我就来介绍一下Plop如何帮助我们在开发过程中提高工作效率。
安装
npm install --save-dev plop
//或
yarn add -D plop
#当然你也可以把它全局安装
npm install -g plop
然后在项目的根目录创建一个plopfile.js
module.exports = function (plop) {};
快速上手
配置
大致涉及这些文件:
├── plop-templates # templates模板
│ ├── cpv # cpv
│ ├── index.hbs # 模板定义
│ └── prompt.js # 配置
│ ├── view # view
│ ├── component # component
│ ├── store # store
│ └── utils.js # utils
├── plopfile.js # plopfile配置
├── package.json
└── yarn.lock
//plopfile.js
const cpvGenerator = require('./plop-templates/cpv/prompt');
const viewGenerator = require('./plop-templates/view/prompt');
const componentGenerator = require('./plop-templates/component/prompt');
const storeGenerator = require('./plop-templates/store/prompt.js');
module.exports = function(plop) {
plop.setGenerator('cpv', cpvGenerator);
plop.setGenerator('view', viewGenerator);
plop.setGenerator('component', componentGenerator);
plop.setGenerator('store', storeGenerator);
};
先来一个简单点的配置
//plop-templates/view/index.hbs
{{#if template}}
<template>
<div class="{{ properCase name }}"></div>
</template>
{{/if}}
{{#if script}}
<script>
export default {
name: '{{ properCase name }}',
props: {},
data() {
return {}
},
created() { },
mounted() { },
methods: {}
}
</script>
{{/if}}
{{#if style}}
<style lang="less" scoped>
</style>
{{/if}}
//plop-templates/view/prompt.js
const { notEmpty } = require('../utils.js');
module.exports = {
description: 'generate a view',
prompts: [
{
type: 'input',
name: 'name',
message: 'view name please',
validate: notEmpty('name')
},
{
type: 'checkbox',
name: 'blocks',
message: 'Blocks:',
choices: [
{
name: '<template>',
value: 'template',
checked: true
},
{
name: '<script>',
value: 'script',
checked: true
},
{
name: 'style',
value: 'style',
checked: true
}
],
validate(value) {
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
return 'View require at least a <script> or <template> tag.';
}
return true;
}
}
],
actions: data => {
const name = '{{name}}';
const actions = [
{
type: 'add',
path: `src/view/${name}/index.vue`,
templateFile: 'plop-templates/view/index.hbs',
data: {
name: name,
template: data.blocks.includes('template'),
script: data.blocks.includes('script'),
style: data.blocks.includes('style')
}
}
];
return actions;
}
};
//plop-templates/utils.js
exports.notEmpty = name => v =>
!v || v.trim() === '' ? `${name} is required` : true
//package.json
{
"scripts": {
"new": "plop",
},
}
运行
yarn new
这样即可创建完成了。
使用
plop命令相关主要借助prompt和Inquirer
prompt 主要是命令行输入表单控件,它的相关功能:
- 提示用户输入
- 支持默认值和字段
- 验证
- 各种提示
//表单
var schema = {
properties: {
name: {
pattern: /^[a-zA-Z\s\-]+$/,
message: 'Name must be only letters, spaces, or dashes',
required: true
},
password: {
hidden: true
}
}
};
//
prompt.start();
//获取用户名,密码
prompt.get(schema, function (err, result) {
console.log('Command-line input received:');
console.log(' name: ' + result.name);
console.log(' password: ' + result.password);
});
//这是可用于验证和提示控件的属性的概述:
{
description: 'Enter your password', // 描述
type: 'string', // 类型
pattern: /^\w+$/, // 正则
message: 'Password must be letters', //警告提示
hidden: true, // 如果为true,则不展示
replace: '*', // 替换
default: 'lamepassword', // 默认
required: true // 是否必填
before: function(value) { return 'v' + value; } //回调执行前,执行
}
Inquirer 交互式命令行工具 相关功能:
- 提供错误回调
- 询问操作者问题
- 获取并解析用户输入
- 检测用户回答是否合法
- 管理多层级的提示
| 参数 | 含义 |
|---|---|
| type | 类型 相关值有:input,number,confirm, list,rawlist,expand,checkbox,password,editor |
| name | 存储当前字段的变量 |
| message | 问题的描述 |
| default | 默认值 |
| choices | 列表选项 |
| validate | 验证 |
| filter | 过滤 |
| transformer | 对用户回答的显示效果进行处理 |
| when | 根据前面问题的回答,判断当前问题是否需要被回答 |
| pageSize | 渲染行数 |
| prefix | 修改 message 默认前缀 |
| suffix | 修改 message 默认后缀 |
| askAnswered | 如果答案已经存在,则强制提示该问题。 |
| loop | 启用列表循环。默认值:true |
有了这些配置,我们就可以定义自己的模板了。
最后贴一下部分配置代码:
//在指定文件创建模板和它的组件
const { notEmpty } = require('../utils.js');
const fs = require('fs');
let components = [];
const files = fs.readdirSync('src/view/');
files.forEach(item => {
let stat = fs.lstatSync('src/view/' + item);
if (stat.isDirectory() === true) {
components.push(item);
}
});
module.exports = {
description: 'generate a cpv',
prompts: [
{
type: 'input',
name: 'name',
message: 'cpv name please',
validate: notEmpty('name')
},
{
type: 'list',
name: 'dirName',
message: 'choose name please',
choices: components,
validate: notEmpty('dirName')
},
{
type: 'checkbox',
name: 'blocks',
message: 'Blocks:',
choices: [
{
name: '<template>',
value: 'template',
checked: true
},
{
name: '<script>',
value: 'script',
checked: true
},
{
name: 'style',
value: 'style',
checked: true
}
],
validate(value) {
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
return 'View require at least a <script> or <template> tag.';
}
return true;
}
}
],
actions: data => {
const name = '{{name}}';
const dirName = '{{dirName}}';
const actions = [
{
type: 'add',
path: `src/view/${dirName}/${name}/index.vue`,
templateFile: 'plop-templates/cpv/index.hbs',
data: {
name: name,
template: data.blocks.includes('template'),
script: data.blocks.includes('script'),
style: data.blocks.includes('style')
}
},
{
type: 'add',
path: `src/view/${dirName}/component/CPV${name}.vue`,
templateFile: 'plop-templates/cpv/component.hbs',
data: {
name: name,
template: data.blocks.includes('template'),
script: data.blocks.includes('script'),
style: data.blocks.includes('style')
}
}
];
return actions;
}
};