组件库开发
搭建项目
使用 vite
创建一个 vue 项目
pnpm create vite
安装依赖
pnpm i
安装 element-plus
pnpm install element-plus
改造项目
删除 assets 目录,删除 components 目录,新建 packages 目录,清空App.vue里的代码
组件封装
- 创建组件文件
在src\packages
目录下新建 button 组件
- 导出组件
在src\packages
目录下新建index.js
用于导出组件
- 本地验证组件是否可用
在main.js
中注册组件
在App.vue
中使用按钮
在终端运行pnpm dev
启动项目
组件库打包
配置 vite.config.js 文件,运行打包命令 pnpm build
进行打包
php
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from "path";
export default defineConfig({
build: {
outDir: "lib", //输出目录名称
lib: {
entry: resolve(__dirname, "./src/packages/index.js"),
name: "xzl-ui",
fileName: 'xzl-ui',
},
rollupOptions: {
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量,为了确保在构建后的库文件中能够正确地访问到 Vue 库的 API
globals: {
vue: 'Vue'
}
}
}
},
plugins: [vue()],
})
上传组件库到npm官网
在打包好的 lib 目录下,执行pnpm init
命令初始化 package.json
注册 npm 账号,执行 npm login
登录到 npm。执行npm publish
就可以正式发布到 npm 仓库。
上传成功后可以在 npm官网 上查到自己上传的组件
扩展
组件封装需要考虑哪些因素?
- 单一责任原则: 每个组件应该专注于一个特定的功能或用途。有助于组件的可维护性,使其更容易理解和调试。
- 组件的可复用性: 将通用的功能封装成可复用的组件,这样在不同的地方都可以使用相同的逻辑和界面。尽量使组件的耦合度低,使其能够在不同的上下文中使用。
- 抽象和接口设计: 定义清晰的组件接口,包括props、事件和插槽(slot)等,以便组件的用户能够以一种直观的方式使用它。
- 可定制性: 为组件提供足够的选项和配置,使用户可以根据自己的需求对组件进行定制。这可以通过props、样式类、插槽等方式实现。
- 状态管理: 决定是否需要将状态内置到组件中,或者将状态管理留给组件的使用者。
- 样式和样式隔离: 考虑组件的样式,尽量使用局部作用域的样式,以避免样式污染和冲突。可以使用CSS Modules、Scoped CSS或CSS-in-JS等方式实现样式隔离。
- 文档和示例: 提供清晰的文档和示例,帮助其他开发者了解如何正确使用你的组件。文档应该包括组件的属性、方法、事件以及示例代码。
二次封装组件的技巧及要点
- 保持原有组件的接口
对 Element-plus 的 input 组件进行简单的二次封装,封装一个 MyInput 组件,代码的结构如下:
javascript// 引入组件进行使用 <template> <MyInput></MyInput> </template> // MyInput.vue <template> <div class="my-input"> <el-input></el-input> </div> </template>
继承第三方组件的 Attributes 属性和 Event 事件
xml<template> <div class="my-input"> <el-input v-bind="$attrs"></el-input> </div> </template>
使用第三方组件的 Slots
xml<template> <div class="my-input"> <el-input v-bind="attrs"> <template v-for="(value, name) in slots" #[name]="scope"> <slot :name="name" v-bind="scope || {}"></slot> </template> </el-input> </div> </template> <script setup> import { useSlots } from "vue"; const slots = useSlots(); </script>
使用第三方组件的Methods
xml<template> <div class="my-table"> <el-table ref="table"></el-table> </div> </template> <script lang="ts" setup> import { ref, onMounted, defineExpose } from 'vue' import { ElTable } from 'element-plus' const table = ref(); const expose = {}; onMounted(() => { const entries = Object.entries(table.value); for (const [method, fn] of entries) { expose[method] = fn; } }); defineExpose(expose); </script> <template> <MyTable ref="tableRef"></MyInput> </template> <script lang="ts" setup> import { ref,onMounted } from 'vue' const tableRef = ref() onMounted(() => { console.log(tableRef.value); // 调用子组件中table的方法 tableRef.value.clearSort() }) </script>
组件库文档搭建
Storybook
文档:storybook.js.org/docs/get-st...
Storybook 是一个开源的前端 UI 组件开发和测试工具,它可以让你独立于应用程序来开发和测试 UI 组件。
安装 Storybook
执行命令 pnpm dlx storybook@latest init
安装成功后会在项目中生成如下文件
运行 pnpm storybook
即可直接预览文档
编写 stories
stories 应该放在哪?
组件的 stories 在与组件文件一起存在的 stories 文件中定义。该 stories 文件仅供开发使用,不会包含在生产包中。
story 文件以 .stories.js 结尾,每个 story 文件为一个菜单项,default 导出为页面配置 (组件、标题等)
export 导出为组件的每种 Props 枚举的样式,可添加多种展示方式。
VitePress
VitePress 是什么
VitePress 是一个静态站点生成器,VitePress 获取用 Markdown 编写的内容,对其应用主题,并生成可以轻松部署到任何地方的静态 HTML 页面。
使用场景
文档、博客、档案和营销网站
安装 vitepress
执行命令 pnpm add -D vitepress
初始化项目
使用 pnpm vitepress init
命令构建一个基本项目
启动项目
使用 pnpm run docs:dev
命令启动具有即时热更新的本地开发服务器
编写文档
VitePress 使用 Markdown 生成内容,内置 Markdown 扩展:表格、语法高亮等,同时 Markdown 进行 Vue 增强,每个 Markdown 页面都是 Vue 单文件组件。
在 Markdown 使用 Vue:Markdown 文件中的根级
ini
# Button 按钮
常用的操作按钮
## 基础用法
使用 `type`, `plain`, `round` 和 `circle` 来定义按钮的样式
<script setup>
import XZLButton from '../src/packages/button/index.vue'
</script>
<XZLButton label="Default" />
<XZLButton label="Primary" type="primary" />
<XZLButton label="Success" type="success" />
<div style="margin-top: 12px">
<XZLButton label="Default" round />
<XZLButton label="Primary" type="primary" round />
<XZLButton label="Success" type="success" round />
</div>
::: details 代码
```md
<XZLButton label="Default" />
<XZLButton label="Primary" type="primary" />
<XZLButton label="Success" type="success" />
```
:::