5-2 项目创建前准备阶段

1 项目创建前准备阶段

exec() {
  try {
    // 1. 准备阶段
    this.prepare()
    // 2. 下载模板
    // 3. 安装模板
  } catch(e) {
    log.error(e.message)
  }
}

prepare() {
  // 1. 判断当前目录是否为空
    // 1.1 询问当前是否继续创建
  // 2. 是否启动强制更新
  // 3. 选择创建项目或组件
  // 4. 获取项目的基本信息
}

1.1 判断当前目录是否为空功能开发

  1. 获取当前文件目录 const localPath = process.cwd()
  2. 获取当前目录下的所有代码文件 let fileList = fs.readdirSync(localPath)
  3. 文件过滤 fileList = fileList.filter(file => !file.startsWith('.') && ['node_modules'].indexOf(file) < 0)
  ifCwdEmpty() {
    const localPath = process.cwd()
    let fileList = fs.readdirSync(localPath)
    fileList = fileList.filter(file => !file.startsWith('.') && ['node_modules'].indexOf(file) < 0)
    return !fileList || fileList.length <= 0
  }

1.2 inquirer 基本用法和常用属性入门

文件交互库 inquirer

1. 基本用法

inquirer.prompt([{
  type: 'input',
  name: 'yourName', // 返回的answer中的key
  message: 'your name' // 与用户交互时的提示
}]).then(answers => {
  console.log(answers);
}).catch(error => {
  if(error.isTtyError) {} else {}
})

2. 常用属性

inquirer.prompt([{
  type: 'input',
  name: 'yourName', // 返回的 answer 中的 key
  message: 'your name', // 与用户交互时的提示
  default: 'noname', // 设置默认值
  validate: v => typeof v === 'string', // 输入值校验
  transformer: v => v + '(input your name)', // 展示信息
  filter: v => 'name[' + v + ']' // 处理当前返回结果
}, {
  type: 'number',
  name: 'num',
  message: 'your number:'
}]).then(answers => {
  console.log(answers);
}).catch(error => {
  if(error.isTtyError) {} else {}
})

1.3 inquirer 其他交互形式演示

1. choice

{
  type: 'confirm',
  name: 'choice', 
  message: 'your choice', 
  default: false
}

2. list

{
  type: 'list',
  name: 'choice', 
  message: 'your choice', 
  default: 0,
  choices: [ // 返回的 answer 中的 value 指向选中的value
    { value: 1, name: 'zmoon' },
    { value: 2, name: 'zhangsan' },
    { value: 3, name: 'lisi' },
  ]
}

3. rawlist

{
  type: 'rawlist',
  name: 'choice', 
  message: 'your choice', 
  default: 0,
  choices: [
    { value: 1, name: 'zmoon' },
    { value: 2, name: 'zhangsan' },
    { value: 3, name: 'lisi' },
  ]
}

4. expand

{
  type: 'expand',
  name: 'choice', 
  message: 'your choice', 
  default: 'red',
  choices: [
    { key: 'R', value: 'red' },
    { key: 'G', value: 'green' },
    { key: 'B', value: 'blue' },
  ]
}

5. checkbox

{
  type: 'checkbox',
  name: 'choice', 
  message: 'your choice', 
  default: 0,
  choices: [
    { value: 1, name: 'zmoon' },
    { value: 2, name: 'zhangsan' },
    { value: 3, name: 'lisi' },
  ]
}

6. password

{
  type: 'password',
  name: 'yourPassword', 
  message: 'your password'
}

7. editor

在文本编辑器中输入复杂内容

{
  type: 'editor',
  name: 'yourEditor', 
  message: 'your editor'
}

1.4 强制清空当前目录功能开发

const fse = require('fs-extra')
async prepare() {
  // 1. 判断当前目录是否为空
  const localPath = process.cwd(); // 获取当前文件目录
  if(!this.isDirEmpty(localPath)) {
    let ifContinue = false
    if(!this.force) {
      // 1.1 询问当前是否继续创建
      ifContinue = await inquirer.prompt({
        type: 'confirm',
        name: 'ifContinue',
        default: false,
        message: '当前文件夹不为空,是否继续创建项目?'
      }).ifContinue;
      if(!ifContinue) return
    }
    // 2. 是否启动强制更新
    if(ifContinue || this.force) {
      // 2.1 给用户做二次确认
      const { confirmDelete } = await inquirer.prompt({
        type: 'confirm',
        name: 'confirmDelete',
        default: false,
        message: '是否确认清空当前目录下的文件?'
      });
      if(confirmDelete) {
        // 2.2 清空当前目录
        fse.emptyDirSync(localPath)
      }
    }
  }
}

1.5 获取项目基本信息功能开发

async getProjectInfo() {
  const projectInfo = {}
  // 1. 选择创建项目或组件
  const { type } = await inquirer.prompt({
    type: 'list',
    name: 'type',
    message: '请选择初始化类型',
    default: TYPE_PROJECT,
    choices: [{
      name: '项目',
      value: TYPE_PROJECT
    }, {
      name: '组件',
      value: TYPE_COMPONENT
    }]
  })
  if(type === TYPE_PROJECT) {
    // 2. 获取项目的基本信息
    const o = await inquirer.prompt([{
      type: 'input',
      name: 'projectName',
      message: '请输入项目的名称',
      default: ''
    }, {
      type: 'input',
      name: 'projectVersion',
      message: '请输入项目版本号',
      default: ''
    }])
  } else if(type === TYPE_COMPONENT) {}
  // return 项目的基本信息 object
  return projectInfo
}

1.6 项目名称和版本号合法性校验

const semver = require('semver')
async getProjectInfo() {
  const projectInfo = {}
  // 1. 选择创建项目或组件
  const { type } = await inquirer.prompt({
    type: 'list',
    name: 'type',
    message: '请选择初始化类型',
    default: TYPE_PROJECT,
    choices: [
      { name: '项目',value: TYPE_PROJECT },
      { name: '组件', value: TYPE_COMPONENT }
    ]
  })
  if(type === TYPE_PROJECT) {
    // 2. 获取项目的基本信息
    const o = await inquirer.prompt([{
      type: 'input',
      name: 'projectName',
      message: '请输入项目的名称',
      default: '',
      validate: function(v) {
        // 合法输入提醒
        const done = this.async()
        setTimeout(() => {
          // 首字符必须为英文字符 +尾字符必须为英文或数字 + 字符仅允许'-_'
          // 合法:a, a-b, a_b, a-b-c, a-b1-c1, a1, a1-b, a1_b
          // 不合法:a, a-1, a_1, a-, a_
          if(!/^[a-zA-Z]+([-][a-zA-Z]+[a-zA-Z0-9]*|[_][a-zA-Z]+[a-zA-Z0-9]*|[a-zA-Z0-9]*)$/.test(v)) {
            done('请输入合法的项目名称')
            return
          }
          done(null, true)
        }, 0);
      },
      filter: v => v
    }, {
      type: 'input',
      name: 'projectVersion',
      message: '请输入项目版本号',
      default: '1.0.0',
      validate: function(v) {
        // 合法输入提醒
        const done = this.async()
        setTimeout(() => {
          if(!(!!semver.valid(v))) {
            done('请输入合法的版本号')
            return
          }
          done(null, true)
        }, 0);
      },
      filter: v => {
        if(!!semver.valid(v)) {
          return semver.valid(v)
        } else {
          return v
        }
      }
    }])
  } else if(type === TYPE_COMPONENT) {}
  return projectInfo
}
posted on 2022-12-30 11:21  pleaseAnswer  阅读(20)  评论(0编辑  收藏  举报