Writing in the front

Moving bricks every day, he has already become a CV engineer. Frequently copy and paste, copy and delete, boring and boring. In projects we typically configure shortcuts in the editor to generate snippets of code. It seems that this does not satisfy CV’s desire. It is important to configure some of the business-related template files in your project and then dynamically generate the files. No editor restrictions, better custom configuration, more powerful.

Look at the effect


There are many ways to generate snippets, such as by configuring shortcuts in the code editor. For example, installing plug-ins in vscode also works. While an editor can be implemented, it cannot be more customized.

In large projects, many pages are relatively similar, and the code level is basically similar. Usually, to create a page component, you need to copy the previous page, copy the API configuration file, copy the file in the Store, and then change the relevant variables, often missing changes.

Now we can extract the common parts of this code into a template file and ask if we need to add some code snippets. Pass judgment and then generate the corresponding file. In this way, we can form a general-purpose code generation method that is specific to the project and improve the efficiency of the work no problem.

Main steps:

  1. Extract common code from the project to form a template file
  2. Customize some configuration of the page by collecting ‘queries’
  3. Generate corresponding files

Here use the PLOp tool to do some configuration, let’s have a look!

The installation

Install it in a local project. Run the following command to install it:

// Global installation

npm i -g plop



// Install locally

npm i plop -D

Copy the code

Configure scripts command:

// package.json

"scripts": {

// ...

"g": "plop --plopfile generators/index.js"

// ...

}

Copy the code

Run NPM run g to perform the configuration. Generators /index.js are the entry files for executing commands. Related configurations will be introduced later.

The basic use

The relevant configuration can be referred to the official document. I just introduce my own configuration in the project for your reference.

Here I add on the basis of one of my own projects, the project address is click to view.

Generators /index.js I have configured four commands:

  • Component: Generates common components
  • Views: Generates a page
  • Vuex: Generate modules files in store
  • API: Generates an API configuration file
// Import each module configuration file

const componentGenerrator = require('./component/index.js')

const viewGenerrator = require('./view/index.js')

const storeGenerrator = require('./store/index.js')

const apiGenerrator = require('./api/index.js')



module.exports = plop= > {

/ / component

plop.setGenerator('component', componentGenerrator)

/ / views

plop.setGenerator('views', viewGenerrator)

/ / vuex related

plop.setGenerator('vuex', storeGenerrator)

/ / API

plop.setGenerator('api', apiGenerrator)

}

Copy the code

First, show the directory structure:

├ generators // Where the file to add

├─ API // API related

├─ Component // Component related

├─ Store // Vue related

├─ Utills // Utility functions

├─ View // View related

├ ─index.js // import file

Copy the code

Vuex module

First, preview the effect:


In vuex modules, you generate modules files. Generate a file from the template file and place it in the store/modules folder. The template file is as follows:

//./store/modules.hbs template file

const state = {



}



const mutations = {



}



const actions = {



}



export default {

namespaced: true.

state,

mutations,

actions

}

Copy the code

The template generation is still very simple, we just need to ‘ask’ to get the filename of the generated file, using modules to accept the folder name that the user typed on the command line. Then configure the file path for the build file in Actions. You can view related comments instead of details about related configurations.

attribute type meaning
description String This section describes the command
prompts array Ask the user
actions Array/Function Operation behavior, ifFunction, the input parameter is the parameter collected after the query, returnsactionsconfiguration
//./store/index.js configuration file

module.exports = {

description: 'vuex modules'.// Here is the function description of the plop

// Ask questions

prompts: [

{

type: 'input'.// Problem type This is input

name: 'modules'.This variable can be used in actions and HBS template files

message: 'Please enter module name'./ / the problem

default:'app' // The default answer to the question

}

].

// Operation behavior

actions: [

{

type: 'add'.// Operation type, here is add file

path: '.. /src/store/modules/{{kebabCase modules}}.js'.// The path to the added file

templateFile: './store/modules.hbs' // Path to the template file

}

]

}

Copy the code

KebabCase formats the data, converting modules to a small hump format. Also commonly used are the following keywords to format user input parameters:

  • CamelCase: changeFormatToThis small hump
  • ProperCase /pascalCase: ChangeFormatToThis Large hump

For more keywords, please view related documents click to view

API configuration file

First, preview the effect:

The configuration of the API module is similar to the above operation. I will post the relevant configuration directly and only introduce the different parts.

Prepare the following template files:

// ./api/api.hbs

import Request from '@/utils/request'



export const get{{properCase file}}List = data= > Request.get('{{kebabCase dir}}/{{kebabCase file}}', data)

Copy the code

In the project, I put the API configuration file in/SRC/API directory. The folder name is the module name of the corresponding page, and the file name is the name of the specific page. Therefore, I need to obtain the folder name to be generated in the dir parameter API directory and the file name corresponding to the file parameter by asking.

// ./api/index.js

module.exports = {

description: 'API Profile'.

/ / to ask

prompts: [

{

type: 'input'.

name: 'dir'.

message: 'Please enter folder name'

},

{

type: 'input'.

name: 'file'.

message: 'Please enter file name'

}

].

// Operation behavior

actions: [

{

type: 'add'.

path: '.. /src/api/{{camelCase dir}}/{{camelCase file}}.js'.

templateFile: './api/api.hbs'

}

]

}

Copy the code

Views the page

First, preview the effect:

This configuration is a little more complex than the previous one, but the step-by-step analysis is easy to understand.

Below through the setting of the inquiry, slowly explain!!

  1. Please enter the folder name of views! In this query, duplicate name validation has been added to prompt and re-enter the folder name when a duplicate name is entered. Save user input to the dir variable.

  2. Please enter views name! It is the same as the previous configuration, mainly get the name of the new file. Save to variable name.

  3. Do YOU need to edit popover components? Save the user’s selection in the hasDialog so that you can dynamically judge and generate actions based on the hasDialog in your Actions.

  4. Do you want to add an API profile?

Save the user’s selection in hasApi and judge it in actions. You can run the configured command to generate the file. NPM run g API ${dir} ${name}.

  1. Whether to addvuex mouduleFile?

Similarly, run the NPM run g vuex ${name} command based on the hasVuex value

Documentation for child_process.exec

The actions property can be a function, and the parameter is a user input variable, returning an array of actions configurations.

After the above query, we also get hasDialog, hasApi, hasVuex, name, dir related variables. You also need to dynamically display some code snippets in the.hbs template file.

There are too many template files, so I won’t post them here, just the key parts.

// ./view/components.hbs

import { pagination } from '@/mixins'

{{#if hasApi}}

import { get{{properCase name}}List } from '@/api/{{kebabCase dir}}/{{kebabCase name}}'

{{/if}}

{{#if hasDialog}}

import { {{properCase name}}Dialog } from './components'

{{/if}}



export default {

name: 'Role'.

{{#if hasDialog}}

components: {

{{properCase name}}Dialog

},

{{/if}}

mixins: [pagination], // Encapsulate paging related functions

data () {

return {

{{#if hasApi}}

listApi: get{{properCase name}}List, // The list requests the address

{{/if}}

searchForm: {}

}

},

mounted () {

{{#if hasApi}}

this.getListData()

{{/if}}

},

methods: {

handleCheck (row) {

{{#if hasDialog}}

this.$refs.{{properCase name}}Dialog.openDialog(row, 'check')

{{/if}}

}

}

}

Copy the code

Here are the main configuration files:

// ./view/index.js

const exec = require('child_process').exec

const componentExist = require('.. /utils/index')



module.exports = {

description: 'views the page'.

prompts: [

{

type: 'input'.

name: 'dir'.

default: 'container'.

message: 'Please enter the folder name of views! '.

validate: value= > {

if ((+ /. /).test(value)) {

return componentExist(value) ? 'Component name or views name already exists' : true

}

return 'Please enter folder name of views'

}

},

{

type: 'input'.

name: 'name'.

default: 'page'.

message: 'Please enter views name! '

},

{

type: 'confirm'.

name: 'hasDialog'.

default: true.

message: 'Do I need to edit the popover component? '

},

{

type: 'confirm'.

name: 'hasApi'.

default: true.

message: 'Do you want to add an API profile? '

},

{

type: 'confirm'.

name: 'hasVuex'.

default: true.

message: 'Do you want to add the vuex moudule file? '

}

].



actions: data= > {

const { hasDialog, hasApi, hasVuex, name, dir } = data

const actions = []



actions.push({

type: 'add'.

path: '.. /src/views/{{kebabCase name}}/{{properCase name}}.vue'.

templateFile: './view/view.hbs'

})



if (hasDialog) {

actions.push({

type: 'add'.

path: '.. /src/views/{{kebabCase name}}/components/{{properCase name}}Dialog.vue'.

templateFile: './view/dialog.hbs'

})

actions.push({

type: 'add'.

path: '.. /src/views/{{kebabCase name}}/components/index.js'.

templateFile: './view/components.hbs'

})

}

if (hasApi) {

actions.push(data= > {

const { name } = data

const cmd = `npm run g api ${dir} ${name}`

exec(cmd, (err, res, stderr) => {

if (err || stderr) return err || stderr

process.stdout.write(res)

})

return 'API profile added'

})

}

if (hasVuex) {

actions.push(_= > {

const cmd = `npm run g vuex ${name}`

exec(cmd, (err, res, stderr) => {

if (err || stderr) {

return err || stderr

}

process.stdout.write(res)

})

return 'Vuex Modules configuration file added'

})

}



return actions

}

}

Copy the code

For a complete example, please refer to the project address and ask for a start

One last word

The above is a simple configuration. You can customize templates based on project characteristics to improve work efficiency. If you have better suggestions, welcome to leave a comment, we common exchange learning, common progress. If you find it useful to welcome, like, comment, share!! Thanks!!

In addition, I also opened a personal public account, welcome to pay attention to!!

Wo”
Welcome to pay attention! Stick to it if you like!