介绍
qz-ui 是一个采用 vue3 语法编写,基于 element-plus 进行二次封装的低代码组件库
命令及介绍
安装依赖
npm i
新建一个组件,只需控制台输入相关组件信息, 会根据该信息自动创建组件相关文件
npm run gen
进行开发组件,packages 下编写代码, 并实时预览
npm run dev
进行组件库打包
npm run build:lib
打包并自动修改包版本号后发布到npm
npm run deploy
进行组件库打包并输出打包分析
npm run build:r
组件文档打包 可部署到静态网站
npm run build:doc
更新组件信息, 自动生成组件配置文件、重新生成路由、配置等信息
npm run cfg
生成每个组件的配置文件
npm run build:compCfg
组件开发:
Q: 如何进行一个新的组件开发?
1 安装依赖后运行 npm run gen; 会生成组件相关文件; 以 qz-button 为例, enter确认
PS D:\work_new\dev\resources\qz-ui-components> npm run gen
输入我们的组件名, 一般以Qz开头
? 请输入你要新建的组件名(纯英文,大写开头):QzButton
这里会包含很多组件类型, 这里我们选择 Basic
? 请选择新建的组件类型? (Use arrow keys)
> { "type": "Basic", "desc": "基础" }
{ "type": "Layout", "desc": "布局" }
{ "type": "Form", "desc": "表单" }
{ "type": "Data", "desc": "数据展示" }
{ "type": "Navigation", "desc": "导航" }
{ "type": "Feedback", "desc": "操作反馈" }
{ "type": "Others", "desc": "其他" }
(Move up and down to reveal more choices)
输入我们的组件中文名
? 请输入你要新建的组件名(中文): 按钮
输入我们的组件功能描述
? 请输入组件的功能描述: 这个是我的自定义按钮
输入组件作者
? 请输入组件作者: xks
组件创建成功会进行提示,接下来就是组件开发了
组件新建完毕,请前往 packages/QzButton 目录进行开发
创建QzButton组件配置文件cfg成功!
2 接下来在packages/QzButton/src/index.vue 编写组件代码进行开发; 由于使用了自动导入, vue相关的api可以直接使用无需导入; 在模板中使用类名 qz-button qz-ui-custom-component以防止样式污染; props在cfg.js中定义
<script setup>
import { ElButton } from 'element-plus';
// import { useAppCore } from 'shared'; // 导入AppCore 为了运行态与组件建立联系 一般不需要此操作
// import { ref, computed } from 'vue'; // 自动导入 不需要此操作
import { getCfg } from '../cfg.js'; // 导入组件属性
const props = defineProps(getCfg().props); // 使用组件属性
defineOptions({ // 定义组件配置
name: 'QzButton',
inheritAttrs: false, // 是否继承属性 配置json与按钮某些属性校验可能存在冲突
});
const emit = defineEmits(['click']); // 定义emit
const handleClick = (...args) => {
emit('click', ...args);
};
// useAppCore({ id: props?.config?.id, type: 'Button', context: { click: handleClick }, pageId: props.pageId }); // 使用AppCore 传入组件自定义context供外部使用
</script>
<template>
<el-button type="primary" v-bind="props" class="qz-button qz-ui-custom-component" @click="handleClick">
<slot>{{ props.label }}</slot>
<template v-for="slot in Object.keys($slots)" #[slot]="scope" :key="slot">
<template v-if="slot !== 'default'">
<slot v-bind="scope" :key="slot" :name="slot" />
</template>
<template v-else>
<slot v-bind="scope" :key="slot" :name="slot">{{ props.label }}</slot>
</template>
</template>
</el-button>
</template>
让我们看看cfg.js 文件中的内容
import { transformCfg } from 'utils/getCompCfg.js';
export const getQzButtonCfg = () => {
return {
props: [ // props在这里定义, 配置态和组件需要使用
{
label: '文本', // key 说明label
value: 'label', // 使用的字段key
verifyType: 'string', // 校验类型
defaultValue: '按钮', // 默认值,如果不需要不写此项
display: true,
},
{
label: '圆形按钮',
value: 'circle',
verifyType: 'boolean',
defaultValue: false,
type: 'switch',
display: false, // 不需要展示该项到配置态 但是组件内部需要使用
},
],
events: [ // events在这里定义, 配置态需要使用
{
label: '点击',
value: 'onClick',
},
],
methods: [ // methods在这里定义, 配置态需要使用
{
label: '点击',
value: 'click',
},
],
};
};
export const getCfg = () => {
return transformCfg(getQzButtonCfg()); // 将上述配置转换为组件可以使用的props
};
3 样式编写在packages/QzButton/src/index.scss中; 将组件样式与组件分隔开, 以及后续自定义主题样式
.qz-button.qz-ui-custom-component {
--qz-button-custom-xxx: red;
color: var(--qz-button-custom-xxx)
// 在这里编写你的样式代码 直接使用在 variables.scss 文件中定义的scss变量 及css 变量; 可在组件内部及全局variables.scss中定义
}
Q: 如何实时查看效果?
在packages/QzButton/doc 目录编写 demo.vue组件, 可编写多个demo 组件, 推荐命名以 base.demo.vue、xxx.demo.vue命名; 在 packages/QzButton/doc/README.md 引入你的 xxx.demo.vue 组件 Preview 组件包裹
// README.md
<script setup>
// 在这里导入你的组件demo
import demo from './demo.vue'
import baseDemo from './base.demo.vue'
</script>
<Preview comp-name="QzButton" demo-name="demo">
<demo />
</Preview>
<Preview comp-name="QzButton" demo-name="base.demo">
<base-demo />
</Preview>
Q: 组件创建时信息输入错误怎么办? 手动删除路由和导入?
因为此时路由和相关文件导入等配置已经生成,手动删除可能存在问题; 如果你此时还没有进行组件开发, 只需要在packages/list.json中删除组件对应的对象信息
// packages/list.json
[
{ // 删除这个对象
"compName": "QzButton",
"compType": "{ \"type\": \"Basic\", \"desc\": \"基础\" }",
"compZhName": "按钮",
"compDesc": "按钮",
"compAuthor": "xks",
"compClassName": "qz-button"
},
... // 省略其他项
然后运行命令 npm run cfg 即可更新路由及各文件的依赖导入导出信息, 无需其他操作
PS D:\work_new\dev\resources\qz-ui-components> npm run cfg
> @kscommon/qz-ui@1.1.9 cfg D:\work_new\dev\resources\qz-ui-components
> node ./script/genNewComp/index.js update
更新文件成功!
文件及目录介绍:
目录介绍:
build
├──base.config.js // 基础打包配置
├──doc.config.js // 文档打包配置
├──lib.config.js // 库打包配置
├──lib.css.js // 样式打包配置
├──lib.disperse.js // 组件块打包配置
dist // 组件打包输出目录
docs // 组件文档目录
packages // 组件包目录
├── locale // 国际化
├── shared // 公共模块
├── utils // 工具函数等
├── styles // 主题样式
├── Button // 组件
│ ├── docs
│ │ ├── README.md // 组件文档
│ │ └── demo.vue // 交互式预览实例
│ ├── index.js // 模块导出文件
│ └── src
│ └── index.vue // 组件本体
├── index.js // 组件库导出文件
├── listCfgs.js // 组件库组件props导出
├── listOptions.js // 配置态配置文件
└── list.json // 组件列表信息
play // 项目测试目录play
script // 脚本
├── genNewComp // 新建组件的模板及脚本文件
├── compCfg.build.js // 打包组件cfg(props)脚本
├── deploy.js // 修改版本号并发布到npm脚本
├── genCss.js // 拷贝及打包样式导出样式
使用
全局使用
import { createApp } from 'vue'
import App from './App.vue'
import QzUI from '@kscommon/qz-ui';
import 'qz-ui/dist/styles/themes/default.scss';
createApp(App).use(QzUI).mount('#app')
在项目中按需使用
import { QzButton } from 'qz-ui/dist/packages/es/QzButton'; // 或者 import { QzButton } from '@kscommon/qz-ui';
使用组件库中的utils、shared等
import { useLocale, vQzDragSortList, taskController } from 'qz-ui/dist/packages/es/shared';
import { useLocale, unique, EventEmitter, isObject, isFunction } from 'qz-ui/dist/packages/es/utils';
import { Locale } from 'qz-ui/dist/packages/es/locale';
主题定制
qz-ui 使用 scss 定义了一套默认样式变量 default.scss, 定制主题就是编辑这个变量列表配置文件 variables.scss;
第一步:
import 'element-plus/theme-chalk/src/index.scss'; // 依赖element-plus包组件样式 mian.js
// 全局使用时 需要引入themes/index.scss 的scss文件 而不能使用已编译的style.css文件
import QzUI from '@kscommon/qz-ui';
import 'qz-ui/dist/packages/styles/themes/index.scss' // import 'QzUI/dist/style.css';
// 局部使用时 需要引入themes/index.scss 的scss文件 而不能使用已编译的style.css文件
import { QzButton } from 'qz-ui/dist/packages/es/QzButton';
// 或者 import { QzButton } from '@kscommon/qz-ui';
import 'qz-ui/dist/packages/QzButton/index.scss';
// import 'qz-ui/dist/styles/themes/index.scss' // 所有样式
第二步:
项目中新建 vars.scss 文件, vite.config.js中配置该用户自定义的scss变量文件
// 项目中主题自定义样式 修改主题 可覆盖 qi-ui 样式变量
$bg: #fff;
$c: blue;
$base: #130909;
// 在此修改element-plus 主题
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': $base,
),
),
);
// vite.config.js
export default defineConfig({
// 其他配置
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "xxxxxx/vars.scss" as *;`
}
}
}
})
// webpack 配置
{
test: /\.(sa|sc)ss$/,
use: [
{
loader: 'sass-loader',
options: {
data: `@import "xxxxxx/vars.scss";`,
}
}
]
}
使用css变量 (推荐)
在variables.scss 中编写css 变量,在组件的index.scss中直接var(--qz-color-xxx)使用
具体方法查看头部(src/App.vue中useVarCss)
国际化
组件库目录介绍
// 组件库国际化目录
locale
├── lang
│ ├── plus
│ │ ├── en.js // 导出 element-plus 语言包
│ │ └── zh-cn.js // 导出 element-plus 语言包
│ ├── zh-CN.js // 组件库中文语言包
│ └── en-US.js // 组件库英文语言包
├── index.js // 导出文件
项目中使用
先在项目中新建以下文件结构及目录
// 项目中国际化目录
locale
├── lang
│ ├── zh-CN.js // 项目中文语言包
│ └── en-US.js // 项目中英文语言包
├── index.js // 导出文件
// en-US.js
class Lang {
save = 'Save';
confirm = 'Confirm';
cancel = 'Cancel';
userSetting = {
'personal-document': 'personal document',
'modify-password': 'modify password',
'add-user': 'add user',
// 省略其他代码
// zh-CN.js
class Lang {
save = '保存';
confirm = '确认';
cancel = '取消';
userSetting = {
'personal-document': '个人档案',
'modify-password': '更改密码',
'add-user': '新增用户',
// 省略其他代码
接着 App.vue中使用 element-plus 国际化
<script setup>
import { ElConfigProvider } from 'qz-ui';
import { Locale } from 'locale'; // 项目中的国际化
import zhCn from 'qz-ui/dist/packages/es/zh-cn'; // 这里导入element-plus国际化
import en from 'qz-ui/dist/packages/es/en';
const langs = {
'zh-CN': zhCn.default,
'en-US': en.default,
};
const cpLang = computed(() => {
return langs[Locale.currentLang.value];
});
</script>
<template>
<el-config-provider :locale="cpLang">
<div id="app">
<router-view v-slot="{ Component }">
<Suspense>
<div>
<component :is="Component" />
</div>
</Suspense>
</router-view>
</div>
</el-config-provider>
</template>
接着合并组件库和项目中的语言及导出组件库中的方法
/* locale/index.js */
import ZhCNLang from 'locale/lang/zh-CN'; // 项目中的中文语言包
import EnUSLang from 'locale/lang/en-US'; // 项目中的英文语言包
import { Locale as QzLocale } from 'qz-ui/dist/packages/es/locale'; // 导入组件库中的语言类
import { useLocale as QzUseLocale } from 'qz-ui/dist/packages/es/shared'; // 导入组件库中使用切换语言方法
// 项目语言集合
export const langs = reactive({
'zh-CN': new ZhCNLang(),
'en-US': new EnUSLang(),
});
/* 合并组件库和项目中的语言包 */
Object.keys(langs).forEach(lang => {
QzLocale.merge(lang, langs[lang]);
});
export const Locale = QzLocale;
export const useLocale = QzUseLocale;
export default Locale;
组件中使用
<script setup>
import { useLocale } from 'locale/index.js'; // 导入上面的js
const { t, setLang, currentLang } = useLocale('userSetting.'); // userSetting. 取userSetting对象下的key
// setLang('en-US') // 切换到英文
</script>
<template>
<div><span>{{ t('modify-password') }}</span></div>
</template>