ZUI 3 使用组件库来管理组件。库中的每个组件在独立的源码和资源目录中开发(例如 lib/button
),可以被独立打包和使用。
组件库采用 pnpm 的工作空间实现,每个组件作为一个单独的包进行管理,包含独立的版本号和依赖定义。
组件名称使用英文小写字母、数字和 -
短横线组成,但只能以小写字母开头,名称应该尽可能简短且贴合组件功能,例如 button
,通常短横线用于连接多个有意义的单词,例如 input-group
。
每个组件根据其名称在工作空间根目录 lib/
下有一个以组件名称命名的目录来管理源码、文档和配置相关文件,通常目录结构如下:
component-name # 组件目录
├── package.json # 组件元信息定义文件(兼容 npm 包定义)
├── index.html # 组件开发和测试所使用的 HTML 文件
├── README.md # 组件开发和测试的说明文件
├── src/ # 源码目录
│ ├── vars.css # 组件用到的 CSS 变量定义
│ └── main.ts # 组件 JS 模块入口文件,也是作为 rollup 打包时的入口文件
├── doc/ # 组件文档目录
│ ├── README.md # 组件文档主要页面
│ └── xxxxx.md # 组件文档其他页面
├── test/ # 测试文件目录
│ └── test.ts # 测试脚本
package.json
文件用于描述组件的元信息,格式兼容 npm 包定义文件,下面说明用于描述组件新的关键属性:
属性 | 描述 |
---|---|
name |
组件名称,根据工作空间约定,名称需要统一添加前缀 @zui ,例如 '@zui/dropdown' |
description |
组件显示名称,例如 "Dropdown Menu" |
version |
版本,例如 "1.0.0" |
keywords |
关键词,例如 ["button", "menu", "dropdown", "zui:component"] ,通过 'zui:TYPE' 的形式来定义组件类型 |
main |
组件模块入口文件,browser 环境和 node 环境均可使用,默认为 "src/index.ts" |
module |
组件符合 ESM 规范的入口文件,browser 环境和 node 环境均可使用,默认为 "src/index.ts" |
browser |
组件在 browser 环境下的入口文件,默认为 `"src/index.ts" |
module |
为 NodeJS 环境提供的入口文件 |
zui |
ZUI 专属配置 |
dependencies |
该组件依赖的其他组件,例如 {"@zui/icon": "workspace:^1.0.0"} |
browserslist |
使用 browserslist 语法声明该组件支持的浏览器,例如 ["not ie < 11", "> 0.2%"] |
其他属性与 npm 中的定义一致,例如 homepage
、license
、author
。
类型 | 定义 | 打包顺序 |
---|---|---|
css-base |
CSS 基础样式 | 1 |
css-utilities |
CSS 辅助类 | 5 |
control |
基础控件,不包括 JS | 2 |
component |
UI 组件 | 4 |
js-helpers |
JS 辅助方法 | 3 |
js-lib |
JS 库 | 6 |
在 package.json
的 keywords
属性中来定义组件类型,定义方法为 zui:组件类型
,当没有定义组件类型时,默认组件类型为 component
。
不同的组件类型打包引入顺序不一样,其中"CSS 基础样式"(css-base
)永远被首先打包,"CSS 辅助类"(css-utilities
)永远被首先打包。
组件产物类型包括:
类型 | 说明 |
---|---|
css |
CSS |
js |
JavaScript |
media |
图片等媒体文件 |
fonts |
字体 |
应该在 package.json
的 keywords
属性中来指定当前组件包含的产物类型,例如 ["css", "js"]
。
每个组件都应该包含一个 README.md
文件作为开发页面。该文件支持 Markdown 语法,在实际访问时会渲染为 HTML,自动引用当前组件的入口文件 /src/main.ts
。应该在此文件中提供使用该组件的相关示例代码。
该文件的另一个作用是进行自动化测试,当改组件包含 UI 呈现部分时,需要在该文件中定义完整使用示例,方便进行自动化测试。
下面为一个 README.md
文件示例:
# 按钮
## Button
```html:example: flex gap-3
<button type="button" class="btn">Button</button>
<button type="button" class="btn">中文按钮</button>
<button type="button" class="btn" disabled="disabled">禁用的按钮</button>
```
## Button Square
使用工具类 `.-square` 获得方形按钮外观。
```html:example: flex gap-3
<button type="button" class="btn -square">S</button>
<button type="button" class="btn -square">中</button>
<button type="button" class="btn -square" disabled="disabled">禁</button>
```
其中代码块语言类型字符串中的 :example
用于指定此代码需要渲染为实际的 HTML,:example:
之后可以添加渲染为 HTML 时的 <div class="example">
元素上需要添加的额外的 CSS 类名。
组件相关的源码存放在 src/
目录,通常包含如下几个文件:
main.ts
该组件的模块入口文件,作为 rollup 打包时的入口。下面为一个示例:
import './vars.css'; // 引入该组件用到的 CSS 变量定义文件
import './style.css'; // 引入该组件用到的 CSS 文件
import './dropdown.ts'; // 引入该组件的 JS 文件
vars.css
定义该组件可以被重新设置的 CSS 变量,该文件通常被 style.css
导入使用。例如:
:root {
--btn-radius: var(--radius);
--btn-background: var(--color-gray-50);
--btn-border-color: var(--color-gray-300);
}
style.css
定义该组件相关样式。例如:
@import url('./vars.css');
.btn {
@apply px-3 h-8;
border: 1px solid var(--btn-border-color);
background: var(--btn-background);
border-radius: var(--btn-radius);
}
组件或库可以依赖其他组件或库进行实现。
根据依赖引入的位置,可以是内部的,也可以是外部的。内部通常来自当前项目 lib/*
目录,外部来自 npm
仓库。
根据依赖引入的作用包括基础公共依赖、普通依赖和开发依赖,下面分别进行介绍。
基础公共依赖
这是所有组件都需要的依赖,不需要声明。目前公共依赖包括:tailwindcss
。在 /lib/
目录下的任务组件中功能的 .css
文件中都可以自由使用 TailwindCSS 的相关指令(Directives)。
普通依赖
普通依赖用于定义组件对另一个组件或库的依赖,例如头像组 avatar-group
依赖头像 avatar
。普通依赖需要在组件对应的 package.json
文件中通过 dependencies
属性进行声明,例如:
{
"dependencies": {
"@zui/avatar": "workspace:^1.0.0"
}
}
开发依赖
开发依赖通常作为当前组件或库在开发脚本、开发调试页面中的依赖。开发依赖需要在组件对应的 package.json 文件中通过 devDependencies
属性进行声明,例如:
{
"devDependencies": {
"jquery": "^3.6.0"
}
}
普通依赖和开发依赖的区别
普通依赖 | 开发依赖 | |
---|---|---|
作用 | 作为当前组件或库的实现的一部分,没有此依赖,当前组件或库功能不完整 | 作为开发工具或开发页面实现的一部分,当前组件或库的功能不依赖开发依赖 |
使用方式 | 在源码中直接使用 | 不能在源码中直接引用,可能用在开发脚本或开发页面中 |
打包范围 | 单独打包此组件也会将普通依赖进行打包 | 单独打包此组件,不会包含开发依赖的部分 |
- 每个组件功能尽可能单一,支持独立打包
- 组件内的源码可以单独引用(使用 package.json 的
files
属性定义) - 组件的样式变量仅用于快速变更主题风格,包括(颜色、圆角等关键设置)
- 为每个组件添加开发主页(
index.html
),全方位展示组件的用法(区别于文档,此页面面向测试人员和组件开发人员)
执行:
$ pnpm install
执行下面的命令打开一个 Web 服务来进入调试模式:
$ pnpm dev
开发时启动的 Web 服务地址通常为 http://localhost:5173/ ,要对特定组件进行调试开发,只需要添加路径 /component-name/
即可,例如开发调试按钮页面地址为:http://localhost:5173/button/ 。
默认打包
执行:
$ pnpm build
定制打包
打包脚本支持通过参数指定需要打包的组件(库),依次将需要打包的组件名称或第三方库名称追加到命令之后即可,例如以下命令将 ZUI 中的按钮、下拉菜单和面板打包为一个定制版本:
$ pnpm build -- buttton dropdown panel
一个更复杂的例子:
$ pnpm build -- --name=zentao-zui --version=1.0.0 button dropdown panel +jquery@^2.0
打包配置还可以通过一个外部的文件来指定:
$ pnpm build -- ./zentao-zui-build-config.json
其中 ./zentao-zui-build-config.json
文件示例内容如下:
{
"name": "zentao-zui",
"version": "1.0.0",
"libs": [
{"name": "@zui/button", "version": "workspace:latest"},
{"name": "@zui/dropdown", "version": "workspace:latest"},
{"name": "@zui/panel", "version": "workspace:latest"},
{"name": "jquery", "version": "^2.0"},
]
}
打包脚本命令完整参数
--lib, -l
指定需要进行打包的组件或库- 多个组件或库通过空格或逗号拼接,例如
--lib="button dropdown panel"
或--lib=button,dropdown,panel
- 如果省略该参数,则默认打包 ZUI 内置的所有组件
- 当需要打包第三方库时,可以直接指定库在 npm 上的名称,但需要添加
+
作为前缀,例如-l +jquery
- 多个组件或库通过空格或逗号拼接,例如
--name, -n
指定进行打包的名称- 如果省略该参数,则默认名称为
zui-custom
- 如果省略该参数,则默认名称为
--version, -v
指定此次打包的版本号- 如果省略该参数,则使用 ZUI 当前版本号
--config, -c
指定打包配置文件--viteFile -V
指定打包使用的额外的 Vite 配置文件
开发
$ pnpm docs:dev
zui/ # 项目根目录
├── package.json
├── index.html # 开发调试时的入口文件
├── README.md # 开发指南文档
├── config/ # 打包配置管理,包括 Tailwind CSS 打包配置
├── src/ # 调试模式 Web 服务源码
├── lib/ # 组件库目录
├── docs/ # 文档网站目录
├── test/ # 测试脚本目录
├── tools/ # 工具类脚本目录
- Node.js 14+
- 包管理器:pnpm
- 构建工具:Vite
- CSS 工具库:TailwindCSS
- 静态文档网站生成:VuePress
- TypeScript 4.5+
- 字体图标生成:Fantasticon
- 文档页面 Vue.js
- JS 组件开发 preact.js
- WebComponent 框架 Lit、catalyst