Создайте свой собственный свод знаний о строительных лесах / CLI с нуля (4D) 🛠

задняя часть внешний интерфейс
Создайте свой собственный свод знаний о строительных лесах / CLI с нуля (4D) 🛠

Назначение строительных лесов состоит в том, чтобыБыстро построить базовую структуру проекта и предоставить спецификации и соглашения по проекту.. В настоящее время широко используемые в повседневной работе скаффолды включают vue-cli, create-react-app, angular-cli и т. д., все из которых завершают быстрое создание контента с помощью простых команд инициализации.

Скаффолдинг — это инструмент, который мы часто используем, и важное средство для повышения эффективности команд. Поэтому систематическое овладение знаниями о строительных лесах очень важно для разработчиков интерфейса.Даже если многие люди не обязательно будут участвовать в работе над инфраструктурой своих соответствующих отделов или компаний в будущем, систематическое овладение этим навыком также может облегчить наше дальнейшее развитие. Прочтите исходный код.Давайте узнаем вместе😉

1. Простой прототип строительных лесов 🐣

Скаффолдинг заключается в том, чтобы задать несколько простых вопросов при запуске и отобразить соответствующий файл шаблона по результатам ответа пользователя., основной рабочий процесс выглядит следующим образом:

  1. Задавайте вопросы пользователям в интерактивном режиме из командной строки
  2. Сгенерировать файл по результатам ответов пользователя

Например, мы используем vue-cliПри создании проекта vue 👇

шаг 1: запустите команду создания

$ vue create hello-world

шаг 2: задавайте вопросы пользователям

cli-new-project.png

cli-select-features.png

Шаг 3: Создайте файлы проекта, отвечающие потребностям пользователя

# 忽略部分文件夹
vue-project
├─ index.html
├─ src
│  ├─ App.vue
│  ├─ assets
│  │  └─ logo.png
│  ├─ components
│  │  └─ HelloWorld.vue
│  ├─ main.js
│  └─ router
│     └─ index.js
└─ package.json

Ссылаясь на вышеуказанный процесс, мы можем сделать это самиСоздайте простой прототип строительных лесов

1. Запустите cli из командной строки

Цель:Реализовано в командной строкеmy-node-cliчтобы начать наши леса

1.1 Создайте новый каталог проекта my-node-cli

$ mkdir my-node-cli 
$ cd my-node-cli 
$ npm init # 生成 package.json 文件

1.2 Создайте новый файл входа в программу cli.js

$ touch cli.js # 新建 cli.js 文件

Укажите файл записи как cli.js в файле package.json 👇

{
  "name": "my-node-cli",
  "version": "1.0.0",
  "description": "",
  "main": "cli.js",
  "bin": "cli.js", // 手动添加入口文件为 cli.js
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

На данный момент структура каталогов проекта:

my-node-cli      
├─ cli.js        
└─ package.json     

Откройте cli.js для редактирования

#! /usr/bin/env node

// #! 符号的名称叫 Shebang,用于指定脚本的解释程序
// Node CLI 应用入口文件必须要有这样的文件头
// 如果是Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
// 具体就是通过 chmod 755 cli.js 实现修改

// 用于检查入口文件是否正常执行
console.log('my-node-cli working~')

1.3 npm ссылка ссылка на глобальную

$ npm link # or yarn link

Выполнение завершено ✅

image.png

Мы можем протестировать его, ввести my-node-cli в командной строке и выполнить его.

$ my-node-cli

Здесь мы видим, что командная строка выводит

my-node-cli working~

Готово ✔, дальше

2. Запросите информацию о пользователе

Функцию реализации и запроса информации о пользователе нужно представить inquirer.js 👉Документация здесь

$ npm install inquirer --dev # yarn add inquirer --dev

Затем мы настраиваем нашу задачу в cli.js

#! /usr/bin/env node

const inquirer = require('inquirer')

inquirer.prompt([
  {
    type: 'input', //type: input, number, confirm, list, checkbox ... 
    name: 'name', // key 名
    message: 'Your name', // 提示信息
    default: 'my-node-cli' // 默认值
  }
]).then(answers => {
  // 打印互用输入结果
  console.log(answers)
})

Введите my-node-cli в командной строке, чтобы увидеть результат выполнения.

image.png

Здесь мы получаем имя проекта, введенное пользователем{ name: 'my-app' }, 👌

3. Создайте соответствующий файл

3.1 Новая папка шаблона

$ mkdir templates # 创建模版文件夹 

3.2 Создайте два простых файла-примера, index.html и common.css.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>
    <!-- ejs 语法 -->
    <%= name %>
  </title>
</head>
<body>
  <h1><%= name %></h1>
</body>

</html>
/* common.css */
body {
  margin: 20px auto;
  background-color: azure;
}

Структура каталогов на данный момент

my-node-cli           
├─ templates          
│  ├─ common.css      
│  └─ index.html      
├─ cli.js             
├─ package-lock.json  
└─ package.json       

3.3 Затем доведите до совершенства логику генерации файлов

Здесь данные, введенные пользователем, отображаются в файле шаблона с помощью механизма шаблонов ejs.

npm install ejs --save # yarn add ejs --save

После доработки переходим на cli.js 👇

#! /usr/bin/env node

const inquirer = require('inquirer')
const path = require('path')
const fs = require('fs')
const ejs = require('ejs')

inquirer.prompt([
  {
    type: 'input', //type:input,confirm,list,rawlist,checkbox,password...
    name: 'name', // key 名
    message: 'Your name', // 提示信息
    default: 'my-node-cli' // 默认值
  }
]).then(answers => {
  // 模版文件目录
  const destUrl = path.join(__dirname, 'templates'); 
  // 生成文件目录
  // process.cwd() 对应控制台所在目录
  const cwdUrl = process.cwd();
  // 从模版目录中读取文件
  fs.readdir(destUrl, (err, files) => {
    if (err) throw err;
    files.forEach((file) => {
      // 使用 ejs 渲染对应的模版文件
      // renderFile(模版文件地址,传入渲染数据)
      ejs.renderFile(path.join(destUrl, file), answers).then(data => {
        // 生成 ejs 处理后的模版文件
        fs.writeFileSync(path.join(cwdUrl, file) , data)
      })
    })
  })
})

Аналогично выполните my-node-cli в консоли, в это времяindex.html,common.cssбыл успешно создан ✔

Распечатаем текущую структуру каталогов 👇

my-node-cli           
├─ templates          
│  ├─ common.css      
│  └─ index.html      
├─ cli.js             
├─ common.css .................... 生成对应的 common.css 文件        
├─ index.html .................... 生成对应的 index.html 文件        
├─ package-lock.json  
└─ package.json       

Откройте сгенерированный файл index.html и посмотрите

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- ejs 语法 -->
  <title>
    my-app
  </title>
</head>

<body>
  <h1>my-app</h1>
</body>

</html>

Пользовательский ввод{ name: 'my-app' }Уже добавлено в сгенерированный файл ✌️

Нажмите здесь, чтобы открыть 👉адрес источника my-node-cli

2. Популярная библиотека инструментов для строительных лесов 🔧

При построении каркаса в реальном производстве или чтении исходного кода другого каркаса вам необходимо понимать следующие библиотеки инструментов 👇

название Введение
commander Пользовательские инструкции командной строки
inquirer Командная строка задает пользователю вопросы и записывает ответы
chalk Улучшение стиля содержимого вывода консоли
ora стиль загрузки консоли
figlet консоль печать логотипа
easy-table форма вывода консоли
download-git-repo Скачать удаленный шаблон
fs-extra Расширение системного модуля fs, предоставляет более удобный API и наследует API модуля fs.
cross-spawn Поддерживает кроссплатформенный вызов команд в системе

Сосредоточьтесь на следующем, другие инструменты могут просматривать документацию

1. пользовательская команда командной строки командира

Больше использования 👉китайский документ

Простой случай 👇

1.1 Создайте новый простой проект Node Cli

// package.json
{
  "name": "my-vue",
  "version": "1.0.0",
  "description": "",
  "bin": "./bin/cli.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "T-Roc",
  "license": "ISC",
  "devDependencies": {
    "commander": "^7.2.0"
  }
}

Структура каталога:

npms-demo             
├─ bin                
│  └─ cli.js          
├─ package-lock.json  
└─ package.json              

1.3 Ввести командира для написания кода

# 安装依赖
npm install commander # yarn add commander 

Улучшить код bin.js

#! /usr/bin/env node

const program = require('commander')

program
.version('0.1.0')
.command('create <name>')
.description('create a new project')
.action(name => { 
    // 打印命令行输入的值
    console.log("project name is " + name)
})

program.parse()

1.3 npm ссылка ссылка на глобальную

  • воплощать в жизньnpm linkбудет применятьсяmy-vueссылка на глобальную
  • После этого выполните в командной строкеmy-vue

Взгляните на вывод из командной строки 👇

~/Desktop/cli/npms-demo ->my-vue

Usage: my-vue [options] [command]

Options:
  -V, --version   output the version number
  -h, --help      display help for command

Commands:
  create <name>   create a new project
  help [command]  display help for command

В это время естьmy-vueИнструкции по использованию команды, команда создания, которую мы только что создали, появляется в разделе «Команды».create <name>, давайте запустим его в командной строке

~/Desktop/cli/npms-demo ->my-vue create my-app
project name is my-app

В это время консоль выведет следующую команду создания.<name>ценностьmy-app👏

2. инструмент для украшения командной строки мелом

мел (мел) можетУкрасить стиль того, что мы выводим в командной строке, например добавление цвета к ключевой информации

2.1 Установить зависимости

npm install chalk # yarn add chalk

2.2 Основное использование

Откройте bin/cli.js в проекте npms-demo.

#! /usr/bin/env node

const program = require('commander')
const chalk = require('chalk')

program
.version('0.1.0')
.command('create <name>')
.description('create a new project')
.action(name => { 
    // 打印命令行输入的值

    // 文本样式
    console.log("project name is " + chalk.bold(name))

    // 颜色
    console.log("project name is " + chalk.cyan(name))
    console.log("project name is " + chalk.green(name))

    // 背景色
    console.log("project name is " + chalk.bgRed(name))

    // 使用RGB颜色输出
    console.log("project name is " + chalk.rgb(4, 156, 219).underline(name));
    console.log("project name is " + chalk.hex('#049CDB').bold(name));
    console.log("project name is " + chalk.bgHex('#049CDB').bold(name))
})

program.parse()

Запустите проект из командной строкиmy-vue create my-appВзгляните на эффект

image.png

Таблица сравнения конкретных стилей выглядит следующим образом 👇

image.png

3. интерактивный инструмент командной строки inquirer

Больше использования 👉адрес документа

специалист по строительным инструментамЧастота использования очень высокаДа, на самом деле вышеПростой прототип строительных лесов, мы уже использовали его, поэтому я не буду его слишком подробно представлять.

4. Анимация загрузки командной строки ora

Больше использования 👉адрес документа

// 自定义文本信息
const message = 'Loading unicorns'
// 初始化
const spinner = ora(message);
// 开始加载动画
spinner.start();

setTimeout(() => {
    // 修改动画样式

    // Type: string
    // Default: 'cyan'
    // Values: 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white' | 'gray'
    spinner.color = 'red';    
    spinner.text = 'Loading rainbows';

    setTimeout(() => {
        // 加载状态修改
        spinner.stop() // 停止
        spinner.succeed('Loading succeed'); // 成功 ✔
        // spinner.fail(text?);  失败 ✖
        // spinner.warn(text?);  提示 ⚠
        // spinner.info(text?);  信息 ℹ
    }, 2000);
}, 2000);

Вывод командной строки выглядит следующим образом

QQ20210516-173914-HD.gif

5. кросс-платформенная оболочка-инструмент

Больше использования 👉адрес документа

Внутри скаффолдинга его можно использовать для автоматизации выполнения команд оболочки, например:

#! /usr/bin/env node 

const spawn = require('cross-spawn');
const chalk = require('chalk')

// 定义需要按照的依赖
const dependencies = ['vue', 'vuex', 'vue-router'];

// 执行安装
const child = spawn('npm', ['install', '-D'].concat(dependencies), { 
    stdio: 'inherit' 
});

// 监听执行结果
child.on('close', function(code) {
    // 执行失败
    if(code !== 0) {
        console.log(chalk.red('Error occurred while installing dependencies!'));
        process.exit(1);
    }
    // 执行成功
    else {
        console.log(chalk.cyan('Install finished'))   
    }
})

Сделайте то же самое в командной строкеmy-vueПосмотрите на результат выполнения

image.png

Успешно установлено 👍

3. Создайте свои собственные леса 🏗

Давайте сначала назовем наши леса, так же, как Чжурон приземлился на Марсе, почему бы не назвать его:zhurong-cli😆

   .-') _  ('-. .-.             _  .-')                    .-') _             
  (  OO) )( OO )  /            ( \( -O )                  ( OO ) )            
,(_)----. ,--. ,--. ,--. ,--.   ,------.  .-'),-----. ,--./ ,--,'  ,----.     
|       | |  | |  | |  | |  |   |   /`. '( OO'  .-.  '|   \ |  |\ '  .-./-')  
'--.   /  |   .|  | |  | | .-') |  /  | |/   |  | |  ||    \|  | )|  |_( O- ) 
(_/   /   |       | |  |_|( OO )|  |_.' |\_) |  |\|  ||  .     |/ |  | .--, \ 
 /   /___ |  .-.  | |  | | `-' /|  .  '.'  \ |  | |  ||  |\    | (|  | '. (_/ 
|        ||  | |  |('  '-'(_.-' |  |\  \    `'  '-'  '|  | \   |  |  '--'  |  
`--------'`--' `--'  `-----'    `--' '--'     `-----' `--'  `--'   `------' 

Какие основные функции необходимо реализовать:

  1. пройти черезzr create <name>команда для запуска проекта
  2. Попросите пользователя выбрать шаблон для загрузки
  3. Удаленное извлечение файлов шаблонов

Демонтаж строительных ступеней:

  1. Создать проект
  2. Создать команды запуска скаффолдинга (используя командующий)
  3. Задавайте вопросы пользователям, чтобы получить информацию, необходимую для создания (используя Inquirer)
  4. Загрузите удаленные шаблоны (используя download-git-repo)
  5. Опубликовать проект

1. Создайте проект

Ссылаясь на предыдущий пример, сначала создайте простую структуру Node-Cli.

zhurong-cli           
├─ bin                
│  └─ cli.js  # 启动文件      
├─ README.md          
└─ package.json       

Настройте файл запуска скаффолдинга

{
  "name": "zhurong-cli",
  "version": "1.0.0",
  "description": "simple vue cli",
  "main": "index.js",
  "bin": {
    "zr": "./bin/cli.js" // 配置启动文件路径,zr 为别名
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": {
    "name": "T-Roc",
    "email": "lxp_work@163.com"
  },
  "license": "MIT"
}

Просто отредактируйте наш cli.js

#! /usr/bin/env node

console.log('zhurong-cli working ~')

Для облегчения разработки и отладки используйтеnpm linkссылка на глобальную

~/Desktop/cli/zhurong-cli ->npm link
npm WARN zhurong-cli@1.0.0 No repository field.

up to date in 1.327s
found 0 vulnerabilities

/usr/local/bin/zr -> /usr/local/lib/node_modules/zhurong-cli/bin/cli.js
/usr/local/lib/node_modules/zhurong-cli -> /Users/Desktop/cli/zhurong-cli

После того, как вы закончите, проверьте это

~/Desktop/cli/zhurong-cli ->zr
zhurong-cli working ~ # 打印内容

ОК, мы получили нужный печатный контент, следующий

2. Создайте команду запуска скаффолдинга

Кратко проанализируем, что нам делать?

  1. Прежде всего, нам нужно полагаться на командира для выполнения этого требования.
  2. Обратитесь к общим командам vue-cli: create, config и т. д. В последней версии вы можете использовать vue ui для визуального создания.
  3. Если созданный существует, вам нужно подсказать, перезаписать ли

Начни сейчас 😉

2.1 Установить зависимости

$ npm install commander --save

После установки 👇

2.2 Создать команду

Откройте cli.js для редактирования

#! /usr/bin/env node

const program = require('commander')

program
  // 定义命令和参数
  .command('create <app-name>')
  .description('create a new project')
  // -f or --force 为强制创建,如果创建的目录存在则直接覆盖
  .option('-f, --force', 'overwrite target directory if it exist')
  .action((name, options) => {
    // 打印执行结果
    console.log('name:',name,'options:',options)
  })
  
program
   // 配置版本号信息
  .version(`v${require('../package.json').version}`)
  .usage('<command> [option]')
  
// 解析用户执行命令传入参数
program.parse(process.argv);

Введите zr в командной строке, чтобы проверить, успешно ли создана команда.

~/Desktop/cli/zhurong-cli ->zr
Usage: zr <command> [option]

Options:
  -V, --version                output the version number
  -h, --help                   display help for command

Commands:
  create [options] <app-name>  create a new project
  help [command]               display help for command

Мы видим, что в Commands уже естьcreate [options] <app-name>, затем выполните эту команду

~/Desktop/cli/zhurong-cli ->zr create
error: missing required argument 'app-name'

~/Desktop/cli/zhurong-cli ->zr create my-project
执行结果 >>> name: my-project options: {}

~/Desktop/cli/zhurong-cli ->zr create my-project -f
执行结果 >>> name: my-project options: { force: true }

~/Desktop/cli/zhurong-cli ->zr create my-project --force
执行结果 >>> name: my-project options: { force: true }

Успешно получена информация для ввода командной строки 👍

2.3 Выполнить команду

Создайте папку lib и создайте create.js в папке

// lib/create.js

module.exports = async function (name, options) {
  // 验证是否正常取到值
  console.log('>>> create.js', name, options)
}

использовать create.js в cli.js

// bin/cli.js

......
program
  .command('create <app-name>')
  .description('create a new project')
  .option('-f, --force', 'overwrite target directory if it exist') // 是否强制创建,当文件夹已经存在
  .action((name, options) => {
    // 在 create.js 中执行创建任务
    require('../lib/create.js')(name, options)
  })
......

сделай этоzr create my-project, в это время информация, которую мы ввели и вышли, нормально печаталась в create.js

~/Desktop/cli/zhurong-cli ->zr create my-project
>>> create.js
my-project {}

При создании каталога необходимо задуматься над вопросом:Каталог уже существует?

  1. если он существует
    • когда{ force: true }, напрямую удалите исходный каталог и создайте его напрямую
    • когда{ force: false }При запросе пользователя, требуется ли переопределение
  2. Если он не существует, создайте его напрямую

Здесь используется инструмент расширения fs fs-extra, давайте сначала установим его

# fs-extra 是对 fs 模块的扩展,支持 promise 
$ npm install fs-extra --save

Давайте улучшим внутреннюю логику реализации create.js

// lib/create.js

const path = require('path')
const fs = require('fs-extra')

module.exports = async function (name, options) {
  // 执行创建命令

  // 当前命令行选择的目录
  const cwd  = process.cwd();
  // 需要创建的目录地址
  const targetAir  = path.join(cwd, name)

  // 目录是否已经存在?
  if (fs.existsSync(targetAir)) {

    // 是否为强制创建?
    if (options.force) {
      await fs.remove(targetAir)
    } else {
      // TODO:询问用户是否确定要覆盖
    }
  }
}

Логика части запроса, мы продолжим ее улучшать ниже

2.3 Создайте больше команд

Если вы хотите таким же образом добавить и другие команды, описание здесь не будет развернуто, пример следующий 👇

// bin/cli.js

// 配置 config 命令
program
  .command('config [value]')
  .description('inspect and modify the config')
  .option('-g, --get <path>', 'get value from option')
  .option('-s, --set <path> <value>')
  .option('-d, --delete <path>', 'delete option from config')
  .action((value, options) => {
    console.log(value, options)
  })

// 配置 ui 命令
program
  .command('ui')
  .description('start add open roc-cli ui')
  .option('-p, --port <port>', 'Port used for the UI Server')
  .action((option) => {
    console.log(option)
  })

2.4 Улучшение справочной информации

Давайте сначала посмотрим на информацию, которую выводит vue-cli при выполнении --help

image.png

В сравненииzr --helpВ распечатанном результате на одно поясняющее сообщение в конце меньше.Здесь делаем дополнение.На ключевые моменты нужно обратить внимание.Информация описания окрашена, здесь нам нужно использовать инструменты из нашей библиотеки инструментовchalkиметь дело с

// bin/cli.js

program
  // 监听 --help 执行
  .on('--help', () => {
    // 新增说明信息
    console.log(`\r\nRun ${chalk.cyan(`zr <command> --help`)} for detailed usage of given command\r\n`)
  })

2.5 Печать логотипа

Если мы хотим создать весь логотип в это время, библиотека инструментовfigletПросто сделай это 😎

// bin/cli.js

program
  .on('--help', () => {
    // 使用 figlet 绘制 Logo
    console.log('\r\n' + figlet.textSync('zhurong', {
      font: 'Ghost',
      horizontalLayout: 'default',
      verticalLayout: 'default',
      width: 80,
      whitespaceBreak: true
    }));
    // 新增说明信息
    console.log(`\r\nRun ${chalk.cyan(`roc <command> --help`)} show details\r\n`)
  })

Посмотрим на это времяzr --helpКак выглядит печать

WX20210519-224306@2x.png

Он все еще выглядит довольно хорошо, ха-ха 😄

3. Задавайте вопросы пользователям, чтобы получить информацию, необходимую для создания

Здесь, чтобы позвонить нашим старым друзьям inquirer, пусть поможет нам решить проблему взаимодействия с командной строкой

Что мы будем делать дальше:

  1. Остаток от предыдущего шага: спросите пользователя, перезаписывать ли существующий каталог
  2. Пользователь выбирает шаблон
  3. Версия, выбранная пользователем
  4. Получить ссылку для скачивания шаблона

3.1 Спросите, перезаписать ли существующий каталог

Вот проблемы, оставшиеся от предыдущего шага:

  1. Если каталог уже существует
    • когда{ force: false }При запросе пользователя, требуется ли переопределение

Логика фактически завершена, вот содержание запроса

предпочтительно установитьinquirer

$ npm install inquirer --save

Затем спросите пользователя, перезаписывать ли

// lib/create.js

const path = require('path')

// fs-extra 是对 fs 模块的扩展,支持 promise 语法
const fs = require('fs-extra')
const inquirer = require('inquirer')

module.exports = async function (name, options) {
  // 执行创建命令

  // 当前命令行选择的目录
  const cwd  = process.cwd();
  // 需要创建的目录地址
  const targetAir  = path.join(cwd, name)

  // 目录是否已经存在?
  if (fs.existsSync(targetAir)) {

    // 是否为强制创建?
    if (options.force) {
      await fs.remove(targetAir)
    } else {

      // 询问用户是否确定要覆盖
      let { action } = await inquirer.prompt([
        {
          name: 'action',
          type: 'list',
          message: 'Target directory already exists Pick an action:',
          choices: [
            {
              name: 'Overwrite',
              value: 'overwrite'
            },{
              name: 'Cancel',
              value: false
            }
          ]
        }
      ])

      if (!action) {
        return;
      } else if (action === 'overwrite') {
        // 移除已存在的目录
        console.log(`\r\nRemoving...`)
        await fs.remove(targetAir)
      }
    }
  }
}

Давайте проверим это:

  1. Вручную создайте два каталога в текущем каталоге, то есть каталоге, отображаемом в командной строке, здесь они называются my-project и my-project2.
  2. воплощать в жизньzr create my-project, эффект следующий

image.png

  1. воплощать в жизньzr create my-project2 --f, сразу видно, что my-project2 удален

⚠️Примечание. Почему удалить только здесь?Потому что после того, как адрес шаблона будет получен позже, каталог проекта будет создан непосредственно при загрузке

3.2 Как получить информацию о шаблоне

Шаблон, который я загрузил в удаленный репозиторий:github.com/zhurong-cli

WX20210520-221040.png

vue3.0-информация о версии шаблона 👇

WX20210520-220540.png

информация о версии vue-template 👇

WX20210520-221400.png

github предоставляет

Мы создаем http.js в каталоге lib, чтобы иметь дело с получением информации о шаблоне и версии.

// lib/http.js

// 通过 axios 处理请求
const axios = require('axios')

axios.interceptors.response.use(res => {
  return res.data;
})


/**
 * 获取模板列表
 * @returns Promise
 */
async function getRepoList() {
  return axios.get('https://api.github.com/orgs/zhurong-cli/repos')
}

/**
 * 获取版本信息
 * @param {string} repo 模板名称
 * @returns Promise
 */
async function  getTagList(repo) {
  return axios.get(`https://api.github.com/repos/zhurong-cli/${repo}/tags`)
}

module.exports = {
  getRepoList,
  getTagList
}

3.3 Шаблон выбора пользователя

Мы специально создаем новый Generator.js для обработки логики создания проекта.

// lib/Generator.js

class Generator {
  constructor (name, targetDir){
    // 目录名称
    this.name = name;
    // 创建位置
    this.targetDir = targetDir;
  }

  // 核心创建逻辑
  create(){

  }
}

module.exports = Generator;

Представьте класс Generator в create.js.

// lib/create.js

...
const Generator = require('./Generator')

module.exports = async function (name, options) {
  // 执行创建命令

  // 当前命令行选择的目录
  const cwd  = process.cwd();
  // 需要创建的目录地址
  const targetAir  = path.join(cwd, name)

  // 目录是否已经存在?
  if (fs.existsSync(targetAir)) {
    ...
  }

  // 创建项目
  const generator = new Generator(name, targetAir);

  // 开始创建项目
  generator.create()
}

Затем напишите логику, чтобы попросить пользователя выбрать шаблон

// lib/Generator.js

const { getRepoList } = require('./http')
const ora = require('ora')
const inquirer = require('inquirer')

// 添加加载动画
async function wrapLoading(fn, message, ...args) {
  // 使用 ora 初始化,传入提示信息 message
  const spinner = ora(message);
  // 开始加载动画
  spinner.start();

  try {
    // 执行传入方法 fn
    const result = await fn(...args);
    // 状态为修改为成功
    spinner.succeed();
    return result; 
  } catch (error) {
    // 状态为修改为失败
    spinner.fail('Request failed, refetch ...')
  } 
}

class Generator {
  constructor (name, targetDir){
    // 目录名称
    this.name = name;
    // 创建位置
    this.targetDir = targetDir;
  }

  // 获取用户选择的模板
  // 1)从远程拉取模板数据
  // 2)用户选择自己新下载的模板名称
  // 3)return 用户选择的名称

  async getRepo() {
    // 1)从远程拉取模板数据
    const repoList = await wrapLoading(getRepoList, 'waiting fetch template');
    if (!repoList) return;

    // 过滤我们需要的模板名称
    const repos = repoList.map(item => item.name);

    // 2)用户选择自己新下载的模板名称
    const { repo } = await inquirer.prompt({
      name: 'repo',
      type: 'list',
      choices: repos,
      message: 'Please choose a template to create project'
    })

    // 3)return 用户选择的名称
    return repo;
  }

  // 核心创建逻辑
  // 1)获取模板名称
  // 2)获取 tag 名称
  // 3)下载模板到模板目录
  async create(){

    // 1)获取模板名称
    const repo = await this.getRepo()
    
    console.log('用户选择了,repo=' + repo)
  }
}

module.exports = Generator;

Проверьте это и посмотрите, как это выглядит сейчас

image.png

Я выбрал шаблон vue по умолчанию, на данный момент

image.png

Успешно получить результат репозитория имени шаблона ✌️

3.4 Пользователь выбирает версию

Процесс тот же, что и в 3.3.

// lib/generator.js

const { getRepoList, getTagList } = require('./http')
...

// 添加加载动画
async function wrapLoading(fn, message, ...args) {
  ...
}

class Generator {
  constructor (name, targetDir){
    // 目录名称
    this.name = name;
    // 创建位置
    this.targetDir = targetDir;
  }

  // 获取用户选择的模板
  // 1)从远程拉取模板数据
  // 2)用户选择自己新下载的模板名称
  // 3)return 用户选择的名称

  async getRepo() {
    ...
  }

  // 获取用户选择的版本
  // 1)基于 repo 结果,远程拉取对应的 tag 列表
  // 2)用户选择自己需要下载的 tag
  // 3)return 用户选择的 tag

  async getTag(repo) {
    // 1)基于 repo 结果,远程拉取对应的 tag 列表
    const tags = await wrapLoading(getTagList, 'waiting fetch tag', repo);
    if (!tags) return;
    
    // 过滤我们需要的 tag 名称
    const tagsList = tags.map(item => item.name);

    // 2)用户选择自己需要下载的 tag
    const { tag } = await inquirer.prompt({
      name: 'tag',
      type: 'list',
      choices: tagsList,
      message: 'Place choose a tag to create project'
    })

    // 3)return 用户选择的 tag
    return tag
  }

  // 核心创建逻辑
  // 1)获取模板名称
  // 2)获取 tag 名称
  // 3)下载模板到模板目录
  async create(){

    // 1)获取模板名称
    const repo = await this.getRepo()

    // 2) 获取 tag 名称
    const tag = await this.getTag(repo)
     
    console.log('用户选择了,repo=' + repo + ',tag='+ tag)
  }
}

module.exports = Generator;

проверить, выполнитьzr create my-project

image.png

После выбора посмотрите на результат печати

image.png

На этом работа по заданию окончена, и шаблон можно скачать.

4. Загрузите удаленный шаблон

Скачать удаленные шаблоны нужно использоватьdownload-git-repoИнструментарий, по сути, он тоже есть в меню инструментов, которое мы перечислили выше, но при его использовании нужно обратить внимание на проблему, т.е.обещания не поддерживаются, поэтому здесь нам нужно использовать модуль utilpromisifyспособ пообещать это

4.1 Установка зависимостей и обещание

$ npm install download-git-repo --save

обещать

// lib/Generator.js

...
const util = require('util')
const downloadGitRepo = require('download-git-repo') // 不支持 Promise

class Generator {
  constructor (name, targetDir){
    ...

    // 对 download-git-repo 进行 promise 化改造
    this.downloadGitRepo = util.promisify(downloadGitRepo);
  }
  
  ...
}

4.2 Основная функция загрузки

Далее логика загрузки шаблона

// lib/Generator.js

...
const util = require('util')
const path = require('path')
const downloadGitRepo = require('download-git-repo') // 不支持 Promise

// 添加加载动画
async function wrapLoading(fn, message, ...args) {
  ...
}

class Generator {
  constructor (name, targetDir){
    ...

    // 对 download-git-repo 进行 promise 化改造
    this.downloadGitRepo = util.promisify(downloadGitRepo);
  }
  ...
  
  // 下载远程模板
  // 1)拼接下载地址
  // 2)调用下载方法
  async download(repo, tag){

    // 1)拼接下载地址
    const requestUrl = `zhurong-cli/${repo}${tag?'#'+tag:''}`;

    // 2)调用下载方法
    await wrapLoading(
      this.downloadGitRepo, // 远程下载方法
      'waiting download template', // 加载提示信息
      requestUrl, // 参数1: 下载地址
      path.resolve(process.cwd(), this.targetDir)) // 参数2: 创建位置
  }

  // 核心创建逻辑
  // 1)获取模板名称
  // 2)获取 tag 名称
  // 3)下载模板到模板目录
  // 4)模板使用提示
  async create(){

    // 1)获取模板名称
    const repo = await this.getRepo()

    // 2) 获取 tag 名称
    const tag = await this.getTag(repo)

    // 3)下载模板到模板目录
    await this.download(repo, tag)
    
    // 4)模板使用提示
    console.log(`\r\nSuccessfully created project ${chalk.cyan(this.name)}`)
    console.log(`\r\n  cd ${chalk.cyan(this.name)}`)
    console.log('  npm run dev\r\n')
  }
}

module.exports = Generator;

Завершите эту часть, простые леса сделаны ✅

Посмотрим, как это работает, выполнимzr create my-project

image.png

На данный момент мы видим, что шаблон создан 👏👏👏

zhurong-cli                 
├─ bin                      
│  └─ cli.js                
├─ lib                      
│  ├─ Generator.js          
│  ├─ create.js             
│  └─ http.js               
├─ my-project .............. 我们创建的项目             
│  ├─ public                
│  │  ├─ favicon.ico        
│  │  └─ index.html         
│  ├─ src                   
│  │  ├─ assets             
│  │  │  └─ logo.png        
│  │  ├─ components         
│  │  │  └─ HelloWorld.vue  
│  │  ├─ App.vue            
│  │  └─ main.js            
│  ├─ README.md             
│  ├─ babel.config.js       
│  └─ package.json          
├─ README.md                
├─ package-lock.json        
└─ package.json             

5. Опубликовать проект

Все вышеперечисленное протестировано локально.В реальном использовании вам может потребоваться публикация в репозиторий npm.После глобальной установки через npm перейдите непосредственно в целевой каталог, чтобы создать проект.Как его опубликовать?

  1. Первый шаг — собрать репозиторий на git
  2. Второй шаг — улучшить конфигурацию в package.json.
{
  "name": "zhurong-cli",
  "version": "1.0.4",
  "description": "",
  "main": "index.js",
  "bin": {
    "zr": "./bin/cli.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "files": [
    "bin",
    "lib"
  ],
  "author": {
    "name": "T-Roc",
    "email": "lxp_work@163.com"
  },
  "keywords": [
    "zhurong-cli",
    "zr",
    "脚手架"
  ],
  "license": "MIT",
  "dependencies": {
    "axios": "^0.21.1",
    "chalk": "^4.1.1",
    "commander": "^7.2.0",
    "download-git-repo": "^3.0.2",
    "figlet": "^1.5.0",
    "fs-extra": "^10.0.0",
    "inquirer": "^8.0.0",
    "ora": "^5.4.0"
  }
}

  1. Третий шаг, используйтеnpm publishПубликуйте, обновляйте, когда придет время, обратите внимание на изменение номера версии

image.png

Таким образом, релиз прошел успешно, давайте откроем сайт npm и поищем 🔍

WX20210522-220454@2x.png

Мы уже можем найти его, чтобы мы могли установить его глобально через npm или yarn.

Нажмите здесь, чтобы открыть 👉исходный адрес zhurong-cli

4. Yeoman: универсальная система строительных лесов

yeoman.png

Первоначально выпущенный в 2012 году, Yeoman представляет собой эффективное программное обеспечение для создания шаблонов веб-приложений с открытым исходным кодом, предназначенное для оптимизации процесса разработки программного обеспечения. Программное обеспечение скаффолдинга используется для реализации совместного использования множества различных инструментов и интерфейсов в проекте, а также для оптимизации процесса создания проекта. Позволяет создавать приложения любого типа (Web, Java, Python, C# и т. д.).

Йомен на самом делетри инструментаСумма:

  • йо --- строительные леса, инструменты автоматической генерации
  • grunt, gulp --- инструменты сборки
  • Bower, npm --- инструменты управления пакетами

Строить строительные леса с помощью Yeoman очень просто.yeoman-generatorДавайте быстро сгенерируем шаблон строительных лесов, мы можем построить любой тип проекта через различные генераторы, давайте попробуем 🤓

1. Основное использование Yeoman

Yeoman — это система сборки, здесь нам нужно использовать йо 👇 для постройки строительных лесов.

1.1 Установите йо глобально

$ npm install yo --global # or yarn global add yo

1.2 Установите соответствующий генератор

ты другойgenerator-xxxМогут быть созданы соответствующие проекты, такие какgenerator-webapp,generator-node,generator-vueподождите, здесь мы используемgenerator-nodeдля демонстрации операции.

$ npm install generator-node --global # or yarn global add generator-node

1.3 Запуск генератора с йо

$ mkdir yo-project
$ cd yo-project
$ yo node

так что мы проходимyo + generator-nodeБыстро создайте проект узла, структура каталогов выглядит следующим образом 👇

yo-project
├─ .editorconfig
├─ .eslintignore
├─ .travis.yml
├─ .yo-rc.json
├─ LICENSE
├─ README.md
├─ lib
│  ├─ __tests__
│  │  └─ testCli.test.js
│  └─ index.js
├─ package-lock.json
└─ package.json          

Как найти нужный генератор? Мы можем перейти к списку генераторов официального сайта для поиска 👉Нажмите здесь, чтобы войти

image.png

Этот способ использования действительно очень прост и удобен, но его недостатки также очевидны--недостаточно гибкий, ведь разные команды используют разные стеки технологий,Что, если мы хотим построить структуру проекта, которую хотим?Тогда смотри вниз 👇

2. Пользовательский генератор

Пользовательский генераторПо сути, это создание определенной структуры пакета npm., эта конкретная структура такая 👇

generator-xxx ............ 自定义项目目录  
├─ generators ............ 生成器目录   
│  └─ app ................ 默认生成器目录      
│     └─ index.js ........ 默认生成器实现
└─ package.json .......... 模块包配置文件

или это 👇

generator-xxx   
├─ app           
│  └─ index.js     
├─ router        
│  └─ index.js   
└─ package.json  

Здесь нужно отметить, что имя проекта должно бытьgenerator-<name>формате, он может быть распознан вами нормально, например, генератор-узел, использованный в приведенном выше примере.

2.1 Создать проект

$ mkdir generator-simple # 创建项目
$ cd generator-simple    # 进入项目目录

2.2 Инициализация нпм

$ npm init # or yarn init

После всего пути входа у нас сгенерировался package.json, но нужно дополнительно проверить:

  • nameЗначение свойства должно быть "генератор-"
  • keywordyoman-generator должен быть включен в
  • filesСвойство должно указывать на каталог шаблонов проекта.

После завершения вышеуказанной работы давайте посмотрим, как выглядит package.json.

{
  "name": "generator-simple",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [ 
    "yeoman-generator" 
  ],
  "files": [
    "generators"
  ],
  "author": "ITEM",
  "license": "MIT"
}

⚠️Примечание: если здесь используется вторая структура каталогов, то необходимо внести некоторые изменения в package.json 🔧

{
  "files": [
    "app",
    "router"
  ]
}

2.3 Установкаyeoman-generator

yeoman-generatorЭто базовый класс Generator, предоставленный Yeoman, что делает более удобным создание пользовательских генераторов.

$ npm install yeoman-generator --save # or yarn add yeoman-generator 

2.4 Инструкции по использованию базового класса Generator

Прежде чем представить базовый класс Generator, давайте реализуем простой 🌰

Сначала откройте файл основной записи и отредактируйте содержимое следующим образом 👇

// ~/generators/app/index.js

// 此文件作为 Generator 的核心入口
// 需要导出一个继承自 Yeoman Generator 的类型
// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入

const Generator = require('yeoman-generator');

module.exports = class extends Generator {
  // add your own methods
  method1() {
    console.log('I am a custom method');
  }
  method2() {
    console.log('I am a custom method2');
  }
};

После этого проходимnpm linkспособ связать проект с глобальным

$ npm link # or yarn link

Таким образом, мы можем получить глобальный доступ к проекту-генератору, давайте попробуем.

$ yo simple

Взгляните на вывод консоли

I am a custom method1
I am a custom method2

Хорошо, это тот результат, который нам нужен 😎

⚠️Уведомление, если работаетyo simpleВозникает следующая ошибка

This generator (simple:app) 
requires yeoman-environment at least 3.0.0, current version is 2.10.3,
try reinstalling latest version of 'yo' or use '--ignore-version-check' option

Это можно обработать следующим образом:

Вариант первый

# 卸载当前版本
npm uninstall yeoman-generator

# 安装低版本的包
npm i yeoman-generator@4.13.0

# 执行
yo simple

Вариант 2

# 全局安装模块
npm i -g yeoman-environment

# 新的执行方式(yoe没有打错)
yoe run simple

Из небольшого 🌰 выше мы видим, что наш пользовательский метод автоматически выполняется последовательно, а базовый класс Generator также предоставляет некоторые последовательно выполняемые методы, похожие на жизненный цикл, давайте посмотрим, что 👇

  1. initializing-- методы инициализации (проверить статус, получить конфигурацию и т.д.)
  2. prompting-- Получить данные о взаимодействии с пользователем (this.prompt())
  3. configuring-- Отредактируйте и настройте файл конфигурации проекта
  4. default-- Если внутри Генератора есть метод, который не соответствует ни одному имени задачи очереди задач, он будет запущен под задачей по умолчанию.
  5. writing-- заполнить предустановленный шаблон
  6. conflicts-- обрабатывать конфликты (только для внутреннего использования)
  7. install-- Установить зависимости (например: npm, Bower)
  8. end-- последний звонок, сделайте чистую работу

2.5 Запустите наш собственный генератор

Мы используем метод, предоставленный Generator, давайте преобразуем входной файл

// ~/generators/app/index.js

const Generator = require('yeoman-generator');

module.exports = class extends Generator {
  // yo 会自动调用该方法
  writing () {
    // 我们使用 Generator 提供的 fs 模块尝试往目录中写入文件
    this.fs.write(
      // destinationPath() 基于项目地址
      this.destinationPath('temp.txt'), // 写入地址
      Math.random().toString() // 写入内容
    )
  }
};

запустить его

$ yo simple

В это время вывод консолиcreate temp.txt, давайте распечатаем структуру каталогов

generator-simple      
├─ generators         
│  └─ app             
│     └─ index.js     
├─ package-lock.json  
├─ package.json       
└─ temp.txt .............. writing 中创建的文件        

Откройте только что созданный temp.txt и посмотрите

0.8115477932475306

Вы можете видеть, что в файл записывается строка случайных чисел.

В реальном использовании нам нужно создать несколько файлов с помощью шаблонов.В настоящее время нам нужно разобраться с этим 👇

во-первых, создайте каталог файлов шаблона./generators/app/templates/, и добавьте файл шаблона в папкуtemp.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- yo 支持 ejs 语法 -->
  <title><%= title %></title>
</head>
<body>
  <% if (success) { %>
    <h1>这里是模版文件<%= title %></h1>
  <% } %>
</body>
</html>

потом, измените файл записи 👇

// ~/generators/app/index.js

const Generator = require('yeoman-generator');

module.exports = class extends Generator {
  // yo 会自动调用该方法
  writing () {
    // 我们使用 Generator 提供的 fs 模块尝试往目录中写入文件
    // this.fs.write(
    //   this.destinationPath('temp.txt'),
    //   Math.random().toString()
    // )

    // 模版文件路径,默认指向 templates
    const tempPath = this.templatePath('temp.html')
    // 输出目标路径
    const output = this.destinationPath('index.html')
    // 模板数据上下文
    const context = { title: 'Hello ITEM ~', success: true}

    this.fs.copyTpl(tempPath, output, context)
  }
};

после завершения,yo simpleЗапускаем его, так мы попадаем в корневую директориюindex.html, открой и посмотри 🤓

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- 支持 ejs 语法 -->
  <title>Hello ITEM ~</title>
</head>
<body>
  
    <h1>这里是模版文件Hello ITEM ~</h1>

</body>
</html>

Переменные, написанные ejs, успешно заменены данными ✌️

следующий, как мы можем получить определенные пользователем данные через взаимодействие с командной строкой, такие как: имя проекта, номер версии и т. д.

Это требует использования Promting, предоставляемого Generator, для обработки некоторых взаимодействий в командной строке.

// ~/generators/app/index.js

const Generator = require('yeoman-generator');

module.exports = class extends Generator {
  // 在此方法中可以调用父类的 prompt() 方法与用户进行命令行询问
  prompting(){
    return this.prompt([
      {
        type: 'input', // 交互类型
        name: 'name', 
        message: 'Your project name', // 询问信息
        default: this.appname // 项目目录名称,这里是 generator-simple
      }
    ])
    .then(answers => {
      console.log(answers) // 打印输入内容
      this.answers = answers // 存入结果,可以在后面使用
    })
  }
  // yo 会自动调用该方法
  writing () {
    ......
  }
};

После сохранения запуститеyo simple

image.png

Мы видим, что командная строка спрашиваетYour Project name ?, после завершения пользовательского ввода мы получаем ответы, чтобы использовать результат в следующем процессе.

// ~/generators/app/index.js
...
// 模板数据上下文
 writing () {
    ...
    // 模板数据上下文
    const context = { title: this.answers.name, success: true}

    this.fs.copyTpl(tempPath, output, context)
  }
...

запустить его сноваyo simple, см. вывод index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- 支持 ejs 语法 -->
  <title>my-project</title>
</head>
<body>
  
    <h1>这里是模版文件my-project</h1>
  
</body>
</html>

Мы можем видеть, что пользователь ввел{ name: 'my-project' }Уже отображается в нашем index.html 👌

Нажмите здесь, чтобы открыть 👉генератор-простой исходный адрес

Вот и все, йомен, давайте взглянем на еще один инструмент для строительных лесов — шлеп 👇

Пять, шлеп: маленький и красивый инструмент для строительных лесов

Плоп небольшой по размеру и легкий по размеру, а красота в его простоте и удобстве использования

Больше способов использования 👉документация по использованию plop

Мы можем напрямую интегрировать его в проект, чтобы решить повторяющуюся и стандартизированную работу по созданию.Давайте сделаем небольшой случай, например

Мы согласовали спецификацию создания компонента:

  • Используйте большой верблюжий регистр для имен компонентов
  • Стиль надо выкручивать отдельно писать
  • Требуемая документация

Процесс использования plop можно грубо разобрать на:

  1. Установите plop, добавьте новый файл конфигурации plopfile.js
  2. Отредактируйте файл конфигурации plop
  3. Создать файл шаблона
  4. Выполнить задание на создание

Теперь введите часть кода

1. Установите шлеп

Сначала инициализируйте проект vue с помощью нашего zhurong-cli.

# 全局安装
$ npm install zhurong-cli -g 
# 创建 vue 项目
$ zr create plop-demo

Мы здесь для унифицированного использования команды, а plop напрямую интегрирован в проект.

$ npm install plop --save-dev

Создайте файл конфигурации plop plopfile.js в каталоге проекта.

2. Отредактируйте файл конфигурации plop

// ./plopfile.js

module.exports = plop => {
  plop.setGenerator('component', {
    // 描述
    description: 'create a component',
    // 询问组件的名称
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'Your component name',
        default: 'MyComponent'
      }
    ],
    // 获取到回答内容后续的动作
    actions: [
      //每一个对象都是一个动作
      {
        type: 'add', // 代表添加文件
        // 被创建文件的路径及名称
        // name 为用户输入的结果,使用 {{}} 使用变量
        // properCase: plop 自带方法,将 name 转换为大驼峰
        path: 'src/components/{{ properCase name }}/index.vue',
        // 模板文件地址
        templateFile: 'plop-templates/component.vue.hbs'
      },
      {
        type: 'add',
        path: 'src/components/{{ properCase name }}/index.scss',
        templateFile: 'plop-templates/component.scss.hbs'
      },
      {
        type: 'add',
        path: 'src/components/{{ properCase name }}/README.md',
        templateFile: 'plop-templates/README.md.hbs'
      }
    ]
  })
}

Метод propCase используется выше для преобразования имени в большой горб, а другие форматы включают 👇

  • camelCase: changeFormatToThis
  • snakeCase: change_format_to_this
  • dashCase/kebabCase: change-format-to-this
  • dotCase: change.format.to.this
  • pathCase: change/format/to/this
  • properCase/pascalCase: ChangeFormatToThis
  • lowerCase: change format to this
  • sentenceCase: Change format to this,
  • constantCase: CHANGE_FORMAT_TO_THIS
  • titleCase: Change Format To This

Мы видим, что файл шаблона был указан выше, но мы его еще не создали, поэтому давайте создадим его

3. Создайте файл шаблона

Создайте папку plop-templates в папке проекта и создайте в ней соответствующий файл шаблона.

plop-templates         
├─ README.md.hbs ............... 说明文档模板     
├─ component.scss.hbs .......... 组件样式模板
└─ component.vue.hbs ........... 组件模板

Мы используем механизм шаблонов Handlebars, более подробное описание синтаксиса 👉Руль Китайский

Отредактируйте component.scss.hbs

{{!-- ./plop-templates/component.scss.hbs --}}
{{!-- dashCase/kebabCase: change-format-to-this --}}
{{!-- name: 输入模板名称 --}}

.{{ dashCase name }} {

}

Отредактируйте component.vue.hbs

{{!-- ./plop-templates/component.vue.hbs --}}

<template>
  <div class="{{ dashCase name }}">{{ name }}</div>
</template>

<script>
  export default {
    name: '{{ properCase name }}',
  }
</script>

<style lang="scss">
@import "./index.scss";

</style>

Изменить README.md.hbs

{{!-- ./plop-templates/README.md.hbs --}}

这里是组件 {{ name }} 的使用说明

Дополнительные инструкции:

  • Шаблоны здесь наиболее просты в реализации, в реальном производстве содержимое шаблона может быть дополнено в соответствии с требованиями.
  • Тире и правильный регистр в шаблоне — это правила отображения для команды изменения имени, которые были перечислены выше.
    • dashCase: становится горизонтальной ссылкой aa-bb-cc
    • properCase: становится большим горбом AaBbCc
    • ...
  • Используя переменные в Handlebars, используйте{{}}пакет

4. Выполните задачу создания

Откройте package.json

// scripts 中 增加一条命令
...
"scripts": {
    ...
    "plop": "plop"
  },
...  

В этот момент мы можем использоватьnpm run plopдля создания компонента

image.png

image.png

Скоро компонент будет создан ✅

Взгляните на папку компонентов на этом этапе

components         
├─ MyApp           
│  ├─ README.md    
│  ├─ index.scss   
│  └─ index.vue    
└─ HelloWorld.vue  

Компоненты MyApp созданы, давайте откроем файлы внутри и посмотрим

Откройте MyApp/index.vue

<template>
  <div class="my-app">my-app</div>
</template>

<script>
  export default {
    name: 'MyApp',
  }
</script>

<style lang="scss">
@import "./index.scss";

</style>

Откройте MyApp/index.scss

.my-app {

}

Откройте MyApp/README.md

这里是组件 my-app 的使用说明

Нажмите здесь, чтобы открыть 👉адрес исходного кода plop-demo

6. Пишите в конце

Я не знаю, дочитали ли вы эту статью, не потеряли ли вы учебу 😂

Эта статья была организована в течение длительного времени, я надеюсь, что она будет полезна для всех в изучении 😁

Кроме того, я надеюсь, что вы можетеНравится Комментарий ПодписатьсяПоддержите, ваша поддержка - движущая сила письма 😘

Предварительный просмотр, следующий принесет 👉Упаковка свода знаний, связанных с инструментами сборки


Справочная статья:

GitHub.com/code маленький П…
process.v ue js.org/this/expensive/adult…
yoman.IO/authoring/я…
woohoo.brief.com/afraid/93211004От…