一键生成组件模板

208 阅读2分钟

参考文章: www.jb51.net/article/118…

1. 运行指令

在package.json添加生成组件模板指令

{
  "scripts": {
    ...
    "new": "node build/new-script.js"
  },
}

在终端输入单层文件 npm run new test src/views(创建位置选填,默认src/conponents)

效果: 在创建位置生成组件名的文件夹test, test文件夹下面有 index.vue、 index.scss、 index.ts。

如果输入多层文件 如: npm run new login/foo

则会先检测conponents文件夹下是否存在login,如不存在,先创建login文件夹,然后创建foo的组件。

2. 编写生成组件模板脚本

获取终端输入的参数

process.argv 第一个参数为nodejs.exe的应用所在绝对路径,第二个参数为当前脚本所在的绝对路径,第三参数是new指令后面的参数

fs模块
fs模块用于对系统文件及目录进行读写操作,本次主要用到的fs模块的功能有:

fs.existsSync(path) 检测文件夹是否存在,一个同步的API,只接受一个路径参数,当前版本异步的废弃了。

fs.mkdir(path,callback) 创建文件夹,异步,两个必填参数,路径和回掉。

fs.writeFile(path,data,callback) 写文件,接受三个参数,文件路径,向文件中写的数据,回掉。

脚本流程

检测空文件夹 --> 创建文件夹/拼接路径 --> 组件模板写入组件

----------- new-script.js -----------
if (!process.argv[2]) {
    console.error('[组件名]必填 - Please enter new component name')
    process.exit(1)
}

let fs = require('fs'); // fs模块
let basePath = process.argv[3] ? (process.argv[3].slice(-1) === '/' ? process.argv[3] : (process.argv[3] + '/')) : 'src/components/'; // 组件保存路径
let path = process.argv[2].split('/'); // 文件名或文件夹/文件名
let name = path[path.length - 1]; // 文件名


/**
 * 检测文件夹是否存在
 * @returns
 */
function exists() {
    return new Promise((resolve) => {
        (async function () {
            // 路径里面有空文件夹
            const basePathList = basePath.split('/')
            basePathList.reduce((prev,cur) => {
                const newPath = prev? (prev+ '/'+ cur) : cur
                if (cur && !fs.existsSync(newPath)) {
                    fs.mkdir(newPath, (err) => {
                    });
                }
                return newPath
            },'')
            // 文件名里面有空文件夹
            for (let a of path) {
                fs.existsSync(basePath + a) ? basePath = `${basePath}${a}/` : await mkdir(a);
            }
            resolve(basePath);
        })()
    })
}
/**
 * 创建文件夹
 * @param {string} a 文件夹名称
 * @returns
 */
function mkdir(a) {
    return new Promise((resolve, reject) => {
        fs.mkdir(basePath + a, (err) => {
            if (err) reject(err);
            basePath = `${basePath}${a}/`
            resolve(basePath);
        });
    })
}

// 模板内容
const files = [
    {
        filename: 'index.vue',
        content:
            `<template>
  <div class="${name}">
    <!--Vue模板编写区域-->
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue'
import usePage from './index'

const { } = usePage()

</script>

<style scoped lang="scss">
@import './index.scss';
</style>`
    },
    {
        filename: 'index.ts',
        content:
            `import { ref, onMounted, watch, computed } from 'vue'
const usePage = () => {
   return {}
}
export default usePage
  `
    },
    {
        filename: 'index.scss',
        content:
            `.${name} {

}`
    },
]

/**
 * 生成文件并写入内容
 * @returns
 */
function writeFile() {
    return new Promise((resolve, reject) => {
        (async function () {
            for (let i = 0; i < files.length; i++) {
                await fs.writeFile(`${basePath}${files[i].filename}`,
                    files[i].content, (err) => {
                        if (err) reject(err)
                    })
            }
            resolve('success');
        })()
    })
}

/**
 * 创建文件
 */
(async function newComponent() {
    try {
        await exists(); // 检测文件名文件夹
        await writeFile(); //写入组件
    }
    catch (err) {
        console.error(err);
    }
})()