想必我们大家在开展一个新项目时,大都采用两种方式,一是直接使用对应脚手架提供的创建方式,比如vue create这样的命令创建vue项目,根据需求,分别安装依赖;二是拿着之前类似项目文件,进行删减、调整。繁琐的过程使开发者直喊奥里给。
现在,光来了!vue-cli 提供了一套模板创建机制,一条命令就可直接复用我们已配置好的初始化项目及依赖,下文我们将详细介绍。
使用方式
git地址: 将模板项目上传仓库使用
本地使用如下命令以远程仓库的为配置创建模板项目
vue create --preset 仓库地址 --clone <project-name>
通过脚手架安装会自动安装好node_modules,所以安装时间可能比较长。
项目介绍
官网地址:cli.vuejs.org/zh/guide/pl…
☆ cli插件开发指南:cli.vuejs.org/zh/dev-guid…
核心文件:preset.json、prompts.js,generator.js
Vue cli preset介绍
preset.json
一个 Vue CLI preset 是一个包含创建新项目所需预定义选项和插件的 JSON 对象,让用户无需在命令提示中选择它们。
在 vue create 过程中保存的 preset 会被放在你的 home 目录下的一个配置文件中 (~/.vuerc)。你可以通过直接编辑这个文件来调整、添加、删除保存好的 preset。
这里有一个 preset 的示例:
{
"useConfigFiles": true,
"cssPreprocessor": "sass",
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
},
"@vue/cli-plugin-router": {},
"@vue/cli-plugin-vuex": {}
}
}
prompts.js
使用方法见npm官网 prompts
Vue cli 需要在prompts.js导出一个包含问题的对象或数组
module.exports = [
{
name: 'selectTemplate',
type: 'list',
message: '请选择模板?',
choices: [
{ name: 'uni-template', value: 'uni-template' },
{ name: 'fant-pc', value: 'fant-pc' },
{ name: 'uni-test', value: 'uni-test', description: "测试和调试脚手架用" },
],
default: 'uni-template'
}
]
**注意:**prompts对象的使用官方提供了很多案列,然而这个prompts的对话过程中只能是线性结构,不能是树状结构。比如我们希望根据用户选择的PC端模板还是app模板在接下来提供不同的选项,这在单次prompts中是做不到的,需要在二次封装。
generator
插件的 Generator 部分通常在你想要为项目扩展包依赖,创建新的文件或者编辑已经存在的文件时需要。
在 CLI 插件内部,generator 应该放在 generator.js 或者 generator/index.js 文件中。它将在以下两个场景被调用:
- 项目初始创建期间,CLI 插件被作为项目创建 preset 的一部分被安装时。
- 当插件在项目创建完成和通过
vue add或者vue invoke单独调用被安装时。
一个 generator 应该导出一个接收三个参数的函数:
- 一个 GeneratorAPI 实例;
- 插件的 generator 选项。
- 整个preset将会作为第三个参数传入。
const prompt = require('prompts');
let public = require('./public/public')//导入公共package
module.exports = async (api, options, rootOptions) => {
// 修改 `package.json` 里的字段
let response,publicResponse
// 公共配置问话
publicResponse = await prompt(require('./public/prompts'))
// 移动端项目模板
if (options.selectTemplate == 'uniapp') {
response = await prompt(require('./uniapp/prompts'));
// 加载项目模板,生成src
api.render('../template/uniapp')
// 加载项目配置文件,生成package.json,根据配置文件加载依赖
api.extendPackage(require('./uniapp/uniapp'))
api.postProcessFiles((files) => {
// rename only main file to main.ts
delete files[api.entryFile]
})
}
// pc项目模板
if (options.selectTemplate == 'fant-pc') {
// 获取配置问话
response = await prompt(require('./fant-pc/prompts'));
if (response.elementUI == '是') {
api.extendPackage({
devDependencies: {
"element-ui": "^2.13.0"
}
})
}
// 加载项目模板
api.render('../template/fant-pc')
// 加载项目配置文件,生成package.json,根据配置文件加载依赖
api.extendPackage(require('./fant-pc/fant-pc'))
}
// end all if
options.response = response //template里只能拿到options,所以要把response挂载到options
api.extendPackage(public)//导入公共package
}
项目结构
index.js (generator入口文件)
public(公共文件)
prompts.js(公共对话模式)
public.js(公共依赖包)
[templateName]
prompts.js
[templateName].js
[templateName]
generator文件夹
generator文件中,不同的模板会使用不同的对话模式,比如PC端会询问是否使用ElementUI,在app端则不用。不同的模板加载的package包也不同,所以项目将不同模板的内容放到了[templaName]文件夹中,prompts.js为这个模板的对话模式,[templateName].js为这个模板需要加载的包,public文件夹中为公共使用的模板和对话模式。
template文件夹
存放模板项目,项目中的package.json文件中的dependencies依赖和devDependencies依赖可以直接复制到generator中,由generator来注入。当对话执行完最终渲染时,在generator文件中调用api.render(src)完成最终渲染。
注意: 如果要渲染一个以点 .开头的文件,则需要改为以下划线 _ 开头,如果要渲染一个以 _开头的文件,则需要改为以双下划线开头 __。
vue-cli拷贝文件是通过EJS模板实现的。EJS文档
html文件中 <%= BASE_URL %>时,需要转义成 <%%= BASE_URL %%>
条件渲染
template文件可以根据用户选择来进行条件渲染,例如:
有如下用户选择
let prompts = [{
type: 'select',
name: 'textView',
message: '首页文字内容显示',
choices: [
{ title: '欢迎使用uni-cli', description: 'recommend', value: 'cli' },
{ title: '欢迎使用uni模板', value: 'template' },
]
}, {
type: 'select',
name: 'colorSelect',
message: '首页文字颜色选择',
choices: [
{ title: '蓝色', description: 'recommend', value: 'blue' },
{ title: '绿色', value: 'green' },
{ title: '红色', value: 'red' },
]
}
]
Vue页面条件渲染如下
<template>
<view class="index">
<%_ if (options.response.textView == 'cli') { _%>
欢迎使用uni-cli
<%_ } _%>
<%_ if (options.response.textView == 'template') { _%>
欢迎使用uni模板
<%_ } _%>
</view>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
})
</script>
<style>
.index{
<%_ if (options.response.colorSelect == 'blue') { _%>
color:blue
<%_ } _%>
<%_ if (options.response.colorSelect == 'green') { _%>
color:green
<%_ } _%>
<%_ if (options.response.colorSelect == 'red') { _%>
color:red
<%_ } _%>
}
</style>
开发流程
- 在根目录的prompts.js中添加新的对话选项,供用户选择你添加的新的模板,可由generator函数的options参数拿到选择结果,选择使用哪个模板的目录。
- 将你的项目模板复制到template文件夹中,如果要引入变量和条件渲染注意用ejs语法。
- 在generator文件夹中创建你的模板文件夹,添加prompts.js对话选项和[templateName].js依赖包
- 将模板的package.json中的依赖复制或者剪切到generator的[templateName].js中,由genenrator控制注入
- 在generator入口文件中根据用户的选择response,使用api.extendPackage()控制包的注入,并调用api.render()渲染模板
- 在template文件夹你的项目模板里根据options.response.[options]控制条件渲染