组件开发作为基建项目也有一年的时间了,这一年对于组件开发总结了一些心得分享给大家,希望对大家有一定帮助
1.组件开发(ts)
1.1 初始化项目
使用vue-cli3直接生成项目,非常便捷,不用自己配一些基础环境,当然你也可以自己搭建不使用webapck使用rollup,可以使代码更加清亮

1.2 组件库项目配置
生成完基本的架子之后需要对项目做一些基本的配置,对照一些大厂的文件夹命名

@types 定义全局的ts声明文件
example 组件库 demoui
lib 组件库打包后的代码
packages 组件库源代码
test 单元测试用例
ts的配置项目不同配置也有差异没有普遍性,目前我们采用的eslint的extends如下
"extends": [
"plugin:vue/essential",
"@vue/standard",
"@vue/typescript/recommended"
],
|
1.3 组件设计

组件库是有多个组件构成,每个文件夹是不同的组件,为了后边打包方便统一入口为index.ts
组件设计:
1. ui规范: 需要抽象和约定一套统一的视觉风格和交互规范。我们的ui规范基本和element-ui保持一致。
2. props设计: 组件库的 props 定义需要具备足够的可扩展性,而且组件内部状态基本依赖props传递,保持组件具有统一的输入
3. callback设计:组件想要暴露给业务代码的数据都是通过callbackback方式回传到父组件
我们以form-table为例
整体风格

筛选部分
暴露筛选前后的插槽,筛选部分通过,父组件通过props传递过来,组件本身通过不同的type实现不同的筛选逻辑

<slot name="before-button">
<!-- 筛选条件之前的button -->
</slot>
|
<div class="item" v-for="(item, i) in domFilter" :key="i">
<span class="label" v-if="item.type !== 'button'">{{item.label}}:</span>
<el-input
v-if="item.type == 'input'"
v-model.trim="pageFilter[item.name]"
size="small"
:placeholder="`请输入${item.label}`"
clearable>
</el-input>
<el-select
v-if="item.type == 'select'"
v-model="pageFilter[item.name]"
size="small"
:placeholder="`请选择${item.label}`"
filterable
clearable>
<div v-if="Object.prototype.toString.call(item.sugMap) === '[object Array]'">
<el-option v-for="(v, i) in item.sugMap" :key="i" :label="v.label" :value="String(v.value)"></el-option>
</div>
<div v-if="Object.prototype.toString.call(item.sugMap) === '[object Object]'">
<el-option v-for="(v, k, i) in item.sugMap" :key="i" :label="v" :value="k"></el-option>
</div>
</el-select>
<el-date-picker
v-if="item.type == 'date'"
v-model="pageFilter[item.name]"
size="small"
:placeholder="`请选择${item.label}`"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:pickerOptions="item.limit ? {
onPick: pickDate => handlePick(pickDate, item.name),
disabledDate: date => item.limit ? disabledDate(date, item.name, item.limit) : false
} : ''"
:editable="false">
</el-date-picker>
<el-date-picker
v-if="item.type == 'datetime'"
v-model="pageFilter[item.name]"
size="small"
:placeholder="`请选择${item.label}`"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:editable="false">
</el-date-picker>
<el-button v-if="item.type == 'button'" size="small" type="primary" @click="item.func">{{ item.label }}</el-button>
</div>
|
<div class="item">
<el-button size="small" type="primary" @click="queryList">查询</el-button>
<!-- 查询之后的button -->
<slot name="after-button" />
</div>
|
table部分
样式,名称,prop通过父组件传递过来,所有的操作的逻辑父组件传递funtion实现

<el-table :data="tableData" border stripe v-loading="loading">
<el-table-column
v-for="(v, i) in tableLabel"
:key="i"
:label="v.label"
:min-width="v.minWidth">
<template slot-scope="scope">
<span>{{ v.extends ? v.extends[scope.row[v.prop]]: scope.row[v.prop]}}</span>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" v-if="Object.keys(tableOperation).length" :min-width="tableOperation.minWidth">
<template slot-scope="scope">
<span v-for="(item, index) in tableOperation.con" :key="index" class="operation">
<el-button
size="small"
:type="item.type"
@click="item.func(scope.row)"
:disabled="item.disabled ? item.disabled(scope.row) : false">
{{ item.label }}
</el-button>
</span>
</template>
</el-table-column>
</el-table>
|
<section page v-if="total">
<el-pagination
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-size="pageSize"
layout="total, prev, pager, next"
:total="total">
</el-pagination>
</section>
|
1.4 组件打包
1.如何打包成所需格式的组件,这种方式是没有办法做到按需加载的
target:打包方式 lib就是组件
name:组件名
dest:打包后的文件夹 打包入口文件
vue-cli-service build --target lib --name sf-vue-ui --dest lib packages/index.ts
|
1.5 组件按需加载
babel-plugin-component,主要借助这个插件的能力
它自动将
import FormTable from 'vudui'
转换成
import FormTable from 'vudui/lib/form-table'
{
"plugins": [
[
"component",
{
"libraryName": "vudui",
"camel2Dash": false, // 是否把驼峰转换成xx-xx的写法
"styleLibraryName": "theme"
}
]
]
}
|
1.6 组件发布npm
npm adduser
npm login
npm publish
2.组件DEMO UI设计
demo 源码都在 examples 目录中维护, npm run dev启动
2.1 结构规划

2.2 ui开发
待续。。。
2.3 demo发布
将demo发布到gh-pages分支
- npm install gh-pages -D
- npm scripts: "deploy":"gh-pages -d dist"
- npm run deploy
3.组件测试
3.1测试框架选择
jest :facebook出,广泛使用在react,vue中,大而全继承了断言库,文档健全
mocha:清亮,所有的东西都需要自定义,文档少
3.2编写测试用例
vue测试jest走过的路,待续。。。
4.组件维护
PR 标题规则:[ bug fix / breaking change / new feature ] 组件名字:修改内容描述
- 前面方括号用来区分 PR / issue 的类型:bug fix - 组件 bug 修复;breaking change - 不兼容的改动;new feature - 新功能
- 修改内容尽可能言简意赅,总结 PR 的改动或者描述 issue
- 描述请用中文
- 组件名字请用英文,首字母大写
PR 用来生成 changelog,规范的 PR 有助于生成比较清晰的 changelog,一目了然
3.组件小tip:
3.1package.json配置:
main:代码入口。这个十分重要,特别是对于组件库。当你想在node_modules中修改你使用的某个组件库的代码时,首先在node_modules中找到这个组件库,第一眼就是要看这个main,找到组件库的入口文件。在这个入口文件中再去修改代码吧
repository:对于组件库很有用。让组件库使用者找到你的代码库地址。这个配置项会直接在组件库的npm首页生效
homepage: 项目主页。对于开发组件库来说挺有用的
keywords:关键词。一个字符串数组,对这个npm包的介绍。组件库必需,便于使用者在npm中搜索。对于公司业务项目,这个配置一般无所谓
desription:包的描述。开发组件库时必需,简明的向库的使用者介绍这个库是干嘛的。对于公司的业务项目,这个配置项一般无所谓
license:开源协议。对于开源组件库,这个十分重要。之前react还因为这事儿没少被社区嫌弃。开源协议略微复杂,用阮一峰前辈的一张图来说明一下吧。注:图里少了ISC, ISC和BSD差不多
3.2 readme徽章
shields.io/