手把手,如何搭建一个通用组件库?(文档+样式+按需打包)

您所在的位置:网站首页 文档样式库怎么导入 手把手,如何搭建一个通用组件库?(文档+样式+按需打包)

手把手,如何搭建一个通用组件库?(文档+样式+按需打包)

2024-03-06 00:31| 来源: 网络整理| 查看: 265

之前的文章# 手把手,如何搭建一个通用组件库,并发布到npm?搭建了一个简单的组件库框架,并发布到了npm。

在文章结果也留了几个个坑,

1.没有样式

2.文档系统也没有

3.组件也不能按需加载

我们今天来一一解决。

样式系统

搭建之前,先来看看element-plus的样式。

image.png

主要分为几个部分,公共样式,混入函数,每个组件对应的样式。

我看了其他几个库,也大概是这种模式。

先看一下var_scss文件。

image.png

通过map定义选项,然后通过map.get来获取对应的值,具体的样式,通过各种函数来进行计算。

image.png

大概思路有了,就来搭建我们自己的样式。

首先是全局样式,以及公用样式。

image.png

具体的组件样式跟函数,我放在组件同级目录中。

image.png

文档系统

文档系统用的是vitepress。

image.png

相比于老大哥vuepress。

vitepress跟vite兼容会更好一些,更轻量一些,但是毕竟比较新,可能坑也会多一些。大家可自行选择。 image.png

快速上手,我就不介绍了,官方有详细的说明。 image.png

安装好了之后,项目跑起来,就能看到一个简单的文档了。

现在我们就可以直接md在上面写vue语法了。

image.png

image.png

并不是很方便,对吧——button需要写两次

我们希望的是写一次,既有效果,又能展示代码片段。

image.png

所以,引入一个插件——vitepress-theme-demoblock。

markdown: { config(md) { // 这里可以使用markdown-it插件 md.use(demoBlockPlugin, { scriptImports: ["import * as bubuUI from '@/index'"], scriptReplaces: [ { searchValue: /import ({.*}) from 'bubu-ui'/g, replaceValue: (s, s1) => `const ${s1} = bubuUI`, }, ], }); }, },

scriptImports里面的配置是将doc文档中的import引入替换成本地文件,这样打包之后就不需要做修改了。开发时请求本地文件,打包后使用npm版本。

注意:vitepress-theme-demoblock插件暂不支持vue3.2.44以后得setup写法。需要使用defineComponent写法,且引入库需要使用单引号。

参考如下。

import { defineComponent, ref } from 'vue'; export default defineComponent({ setup() { const val = ref(false); return { val, }; }, });

docs的详细请求,大家可以看一下官方文档。

我当时是直接拷贝了vitepress官网上的配置,然后修改侧边栏菜单。

配置好的文档长这样。 image.png

按需打包

我们使用ui库一般有2种方式。

一种是全局引入。

import BuBuUI from "bubu-ui" app.use(BuBuUI)

另一种是按需引入。

我们就只管用,不需要管引入的问题,比如我用bu-button,就自动到对应的包中去拿组件。

import BuButton from "bubu-ui/components/button" app.use(BuButton)

所以我们需要,把组件单独打包出来。

我们自己写一个脚本,通过vite的buid方法来构建。

import { defineConfig, build } from 'vite'; build({ build: { // 配置跟vite.config.ts文件基本相同 } })

这个只是全局打包,还需要多走一步,就是遍历components文件夹的组件,找到index.ts入口文件,重新执行一遍build打包。

打包出来的文件如下,components中的就是单独打出来的组件包。

image.png

到这里,还有个问题,ts文件在src/components中,而打包出来的子组件,在components中。(如果打包的时候指定一样的目录,会相互覆盖)

我的解决方案就是写了个拷贝函数,直接把components下的组件,直接拷贝到src/components中。如果哪位大佬有比较优雅的方式,欢迎指正留言,感谢感谢。

// 如果目标文件夹不存在,创建目标文件夹 if (!fse.existsSync(destPath)) { fse.mkdirSync(destPath); } let files; // 读取源文件夹下的所有文件和子文件夹 try { files = fse.readdirSync(srcPath); } catch (err) { return; } // 遍历所有文件和子文件夹 files.forEach((file) => { // 拼接文件路径 const srcFilePath = join(srcPath, file); const destFilePath = join(destPath, file); // 如果是文件夹,递归复制文件夹 if (fse.statSync(srcFilePath).isDirectory()) { copyFolder(srcFilePath, destFilePath); } else { // 如果是文件,复制文件 fse.copyFileSync(srcFilePath, destFilePath); } });

现在单独的组件包也有了,还差最后一步。

按需引入

安装unplugin-vue-components,这也是element-plus用的方案。

配置替换规则。

Components({ dts: true, resolvers: [ (componentName) => { if (componentName.startsWith('Bu')) { return { name: componentName, from: `bubu-ui/src/components/${componentName.slice(2)}` } } } ] })

作用就是,如果有组件是以Bu开头的,就从ui库的src/components下引入组件。然后通过vue的components方法注册组件。

nihao

以上的组件使用方式,就相当于如下写法

nihao import { defineComponent } from "vue" import { BuButton } from "bubu-ui/src/components/button" defineComponent({ components: { BuButton } }) 总结

到这里,一个通用的组件库基本算是搭建完成了,也能发布上线使用了。

但是要真正封装出一个好用的ui组件库,还是有很多细节需要实现。

举几个例子

1.element-plus支持手动按需导入

nihao import { ElButton } from "element-plus"

image.png

他的入口文件,并没有把每个组件都打包进去。

这个有大佬知道怎么弄的,也欢迎联系我,感谢。

2.组件开发过程中的相互引用

在组件开发过程中,如果存在组件相互引用,那么我们最好的方式是开发的时候引用本地,打包上线的时候引用的是对应的模块。

这个就涉及到包模块管理了。

3.element-plus的类型封装

element支持如下2种使用方式,又能当插件,又能当组件。

// 1 import { ElButton } from "element-plus" app.use(ElButton) // 2 import { ElButton } from "element-plus" app.component(ElButton)

在element-plus中,在组件上添加了一个install方法,导出的均为组件本身。

image.png

先到这吧。

后续如果有新的感悟,或者对架构有新的思考再分享。

如果这篇文章对你有所收获,欢迎点赞评论。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3