简介
在之前总结我对Vue项目团队开发的一些基本配置封装分享文章中,我们已经对大部分的常见封装都做出了处理,从API约定式
到Model数据层
,这类行为都赋予了项目更加自动化的处理方式,使团队前端工程师
不需要关注生成,而只需要注意代码结果
和代码质量
,从而得到更多实践上得意义。
同时,对于代码质量的管理在【七日打卡】重构几次代码后,我总结了一些前端代码优化实践中,我们也提到了一些代码的实践优化案例,以及许许多多的条件约束都是为开发者养成好的编码习惯的同时进行探索,为成为更好的前端工程师养成基本习惯。
在这篇文章中。我主要想分享的就是在开发时,项目脚手架和项目架构能为开发人员
做什么处理,是不是能够给与一些实质性的帮助来提升开发的效率和容错率。
什么是【资产】
对于我们开发者来说,平时所构建的代码就是个人资产
,但是大多时候,资产的管理对于团队来说是非常糟糕的,对于资产的管理来说,很多小公司项目都是临时产生的,每一个项目都属于从0
开始。那么,每一次所有的配置,封装都不一样。对于团队来说,所有的项目都没有统一性,新入职的同学需要耗费非常久的时间去学习不同的配置风格,加上老板如果没耐心,需要快速的投入生产,那么这个项目最终其实难逃重构的命运。
因此,对于团队公共资产的管理就变得尤为重要,其中框架的更新肯定会带动资产的更新是必然的趋势,所以这就需要团队在维护资产的方面有一定的经验能力了,毕竟资产维护
是脱离于项目之外的工作量但是,收益方却是整个部门的前端团队。
Plop微型脚手架能干什么?
在这里,我是通过Plop
来管理日常资产
的,对于我们日常写的组件,方法库来说,这类固定资产是必须进行管理的。举个例子,我写了一个微信小程序
处理登录的逻辑块,我将它抽离成一个单独的切片方法。那么,下一次我写小程序是不是只需要将逻辑方法复制过来进行调用就完成了?
Plop
是一个非常小巧的Sub Generator
,对我们来说,将其集成到我们项目的脚手架
中充当一个调度者
。它需要调度的就是我们自身团队维护起来的【开发资产
】,如:UI Desgin
,Utils
, Api约定式生成
, 抽象代码模板
...等等功能的调度生产,大幅度的减少开发者日常CV
,插件
的一些工作。
- 创建对应的UI资产组件
- 创建对应的资产方法
- 创建开发时的API接口函数
- 创建开发目录结构
- 创建开发模板代码
- ...
Plop如何实现这些功能?
在构建时,我们需要做的就是配置setGenerator
,通过命名空间来产生不同的流程方式,决定我们当前需要处理的行为和选择。
plop.setGenerator('test', createPageTemplate)
plop.setGenerator('api', createApiTemplate)
当我们需要创建一个页面的时候,需要运行plop
命令就可以进行对应的页面和组件,而不必像之前一样,先创建文件
,然后创建对应的资源,甚至于,我们还可以进行其他模式的配置,如下图中,你是否需要Modl
和sass
,scss
的选择。
一个简单的setGenerator
一个基本的setGenerator
做的东西可多可少,取决于开发者
需要让其干什么。学习过C语言的同学都应该知道命令行界面
的基本操作吧,通过scanf
来进行输入,根据输入的内容产生对应的逻辑出来,其实这个就和脚手架很像了,只不过脚手架做的东西更多,除了输入框之外,还有列表
,选择器
...等等其他组件元素的存在。
那么,我们来分析以下最基本的页面容器的创建,是怎么进行的吧:
在一个一个简单的setGenerator
中,包含以下4个配置关键字。
comopnent:''
description: 'this is a skeleton plopfile',
prompts: [], // array of inquirer prompts
actions: [] // array of actions
comopnent
:作为setGenerator的命名空间名description
:作为描述,主要用来描述当前需要处理的行为prompts
:作为步骤条提示,可以提示和中断来与用户操作,引导用户进行配置使用。actions
: 作为操作行为,当用户通过提示步骤配置后用来执行相应的动作时产生。
可以到看,其实Plop
的行为不算复杂,大多数都是配置性的工作。因此,在项目周期淡季可以挑选时间做资产
的生成模式。下面是一个普通的setGenerator
,本身没有太多的行为去
页面是如何生成的?
我们通过一个基本的目录生成到路由插入的示例来进行一个Demo
演示吧。下面就是一个基本的演示,主要实现的功能就是项目目录自动构建的同时插入路由,一键创建页面级别的模板。如下图,可以看到moreTest
页面生成后,会自动在routes.js
下面自动插入一个路由声明,达到我们一键生成的目的。
安装plop
可以选择在全局安装,或者仅当前项目安装的形式,通过包管理器安装plop
的运行依赖。
# shell
yarn global add plop
新增启动命令
通过yarn new module
的命令就是通过script
来添加的,名字可以随便取,主要是执行Plop
的脚本。
// package.json
"scripts": {
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"dev": "vue-cli-service serve --mode dev",
"doc": "jsdoc -r -c conf.json README.md",
"new": "plop"
},
创建plopfile
plopfile.js
就是作为plop
配置的entry
文件,主要就是加载不同的setGenerator
。由于我们的setGenerator
可能会是大批量的,建议拆分成一个目录做这件事情。我个人目前是所有设置类型的操作都放在了.setting
目录下,方便管理。
在这里其实相当于一个文件的聚合,主要用来声明对应的配置和setGenerator Name
。主要的代码就是各个模块不同的action
了。
const createPageTemplate = require('./src/.setting/plop/page')
const createApiTemplate = require('./src/.setting/plop/api')
function cli (plop) {
plop.setGenerator('page', createPageTemplate)
plop.setGenerator('api', createApiTemplate)
}
module.exports = cli
prompts
在写prompts
之前,可以先阅读文档,查看prompts
中的配置属性,方便更好的去实现对应的提示操作和选项。
type
: 主要的类型存在:input
,number
,confirm
,list
,rawlist
,expand
,checkbox
,password
,editor
name
: 当前类型存放的变量名,可以通过名称拿到对应的操作值message
: 提示信息,主要是呈现给用户展示default
: 当前选项的默认值choices
:多个选项,一般用于列表展示。其他
:查看Plop
文档,不然别人说我水字数:#Plop Types
在上面的话,我将一些基本的参数都说明了下对应的作用,那么就可以开始写对应的prompts
了,如下代码,就创建了一个input
,list
,confirm
提示组件。让用户进行更好的操作。
prompts: [
{
type: 'input',
name: 'pageName',
message: '请输入页面文件夹名称'
},
{
type: 'list',
name: 'cssType',
default: 'scss',
choices: ['手动', 'sass', 'scss'],
message: '请选择需要创建的sass类型?'
},
{
type: 'confirm',
name: 'isModel',
default: true,
message: '请选择需要创建Model?'
},
],
action
如果说输入的组件完成了,这个时候我们就可以在action
,中拿到对应的值,这些值都是用户操作过后的一些值,我们可以通过这个去进行action
行为的添加。
常见的action
动作有以下几种。
add
: 该操作用于将文件添加到项目中。path 属性是一个处理句柄模板,将用于按名称创建文件。文件内容将由或属性确定。addMany
: 该操作可用于通过单个操作将多个文件添加到项目中,add
的加强版。modify
: 该操作可以使用两种方法。可以使用 属性查找/替换位于指定文件中的文本,也可以使用函数来转换文件内容。append
: 它用于在特定位置将数据追加到文件中, 插入文件数据的作用。
同时常见的属性有:
type
: 上面action
的动作类型path
: 需要操作的路径templateFile
: 模板路径data
: 带入hbs
模板中的数据,在模板中可以获取。
可以看到,在下面我拿到了用户输入的操作值,根据操作值的情况,进行了action
的操作,这里为了直观,并没有使用addMany
来创建文件,而是一步步来进行。如下图和代码,我们可以产生对应的文件目录,文件名,和模板代码。这里其实不难理解,无非就是通过不同的判断,添加了几个action
,最后返回出去了集合数组。
actions: data => {
const { pageName, cssType, isModel } = data
console.log(data)
const actions = []
const name = '{{pageName}}'
const path = `src/${PAGE_PATH}/{{ pageName }}/`
if (pageName) {
actions.push({
type: 'add',
path: `${path}/index.vue`,
templateFile: 'src/.setting/template/view/page.hbs',
data: {
name: pageName,
}
})
}
if (cssType !== '手动') {
actions.push({
type: 'add',
path: `${path}/index.${cssType}`,
templateFile: 'src/.setting/template/view/css.hbs'
})
}
if (isModel) {
actions.push({
type: 'add',
path: `${path}/model.js`,
templateFile: 'src/.setting/template/view/model.hbs',
data: {
name: pageName,
}
})
}
actions.push({
type: 'append',
path: 'src/router/routes.js',
pattern: /\[/,
templateFile: 'src/.setting/template/router/config.hbs',
data: {
name: pageName,
}
})
return actions
}
hbs模板
可能大家发现了,我们的模板是hbs
的,它是一个单纯的模板引擎,作用相比于现在的模板来说虽然优势不明显,但是我们仅仅只是需要一些模板的编写,所以hbs
完全是能够满足我们的一些基本需求的。我们需要创建action
中对应声明的hbs
模板文件,来让plop
创建或者插入到我们声明的path
当中去。
<template>
<div>
<p>页面创建成功,当前页面名称 -- {{ name }}</p>
<p>页面创建成功,当前页面路径 -- @/views/{{ name }}</p>
</div>
</template>
<script>
import { useServices } from 'framework'
const api = useServices()
export default {
name: '{{name}}',
data: () => {}
}
</script>
效果
至此完成,我们的一个基本目录添加就完成了,下面看一下效果吧。看看最终插入到视图上面的内容是不是我们想要的内容吧。
代码=>
const PAGE_PATH = 'views'
module.exports = {
description: '创建文件,注意必须符合项目约束规范',
prompts: [
{
type: 'input',
name: 'pageName',
message: '请输入页面文件夹名称'
},
{
type: 'list',
name: 'cssType',
default: 'scss',
choices: ['手动', 'sass', 'scss'],
message: '请选择需要创建的sass类型?'
},
{
type: 'confirm',
name: 'isModel',
default: true,
message: '请选择需要创建Model?'
},
],
actions: data => {
const { pageName, cssType, isModel } = data
console.log(data)
const actions = []
const name = '{{pageName}}'
const path = `src/${PAGE_PATH}/{{ pageName }}/`
if (pageName) {
actions.push({
type: 'add',
path: `${path}/index.vue`,
templateFile: 'src/.setting/template/view/page.hbs',
data: {
name: pageName,
}
})
}
if (cssType !== '手动') {
actions.push({
type: 'add',
path: `${path}/index.${cssType}`,
templateFile: 'src/.setting/template/view/css.hbs'
})
}
if (isModel) {
actions.push({
type: 'add',
path: `${path}/model.js`,
templateFile: 'src/.setting/template/view/model.hbs',
data: {
name: pageName,
}
})
}
actions.push({
type: 'append',
path: 'src/router/routes.js',
pattern: /\[/,
templateFile: 'src/.setting/template/router/config.hbs',
data: {
name: pageName,
}
})
return actions
}
}
历史文章回溯
- 【七日打卡】重构几次代码后,我总结了一些前端代码优化实践
- 总结我对Vue项目团队开发的一些基本配置封装分享
- 如何在Vue中使用Mixin来管理异步数据的实践思考
- 我在项目中对前端接口请求管理的总结
总结
plop
可维护比较多的模板类资产,随着我们的setGenerator
越来越多,我们的资产库就越来越大,那么除了维护这一部分的代码外,对脚手架的设计也需要明细,尽量能够在界面上提供更好的元素描述,让团队新人开发者或者说入门开发者能够凭借描述来使用对应的资产,而不是在翻阅文档或者是找资产提供人进行询问。
资产
中的设计资产
也同样重要,我们可以尝试和UI
还有交互
共同维护一套跨部分和业务的资产体系,其实涉及的设计体系
,交互操作
,动画模式
都是资产,Plop
只能为开发带来共同的资产维护
,但是团队的资产也可以是来源于外方的。
当积累的资产到达一定的积累时,在制作新的产品,开发的效率会大大提高,相比于从0
到1
,更多的是直接集成资产来进行开发,这个时候大部分设计
,交互
,动画
,基础方法
,组件
,都已经在资产库中存在,我们只需要将其提取出来,然后在页面上进行调用,我们可以有更多的时间方法代码的圈复杂度和逻辑优化上面。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!