个人觉得,组件库最难的不是开发,而是使用,怎么才能让组内同事都用起来,这才是关键

背景

虽然现在开源的组件库很多,但每个项目里还是或多或少都会有人封装出一些项目内通用的基础组件、业务组件

我参与过多个项目,几乎每个项目都会存在这么一种现象:重复造轮子

同一个用途的组件被不同人多次实现,导致后续维护的人可能都不知道该用哪个好,或者干脆又自己撸了一个,就又恶性循环了

至于如何解决,遇到的基本就是强制定规范,但这种靠人为主观意识的约定,很容易松动,不长久

痛点

其实可以来分析下看看,为什么就会用不起来呢?

为什么大家乐意去用一些开源组件库,就是不想用项目里别人封装的呢?

就我个人而言,可能有这么几个原因:

  • 我不知道原来项目里已经有这么个通用组件了
  • 我找到组件代码,但我不确定这个组件呈现效果是什么,是不是我想要的,对业务不熟,与其慢慢去捞页面找试用,干脆自己再撸一个
  • 我找到组件代码,也找到页面呈现效果,但我不知道该怎么使用,需要花时间去看源码

于是我反思,那我为什么会乐意去用开源组件库,比如 element-ui 组件呢:

  • 官网可以直接找到所有组件呈现效果和示例代码
  • 官网的配置项说明足够使用组件,而无需去看源码

所以对我来说,根源不是不想用同事封装的组件,而是懒得去看源码,去找示例

我更在意的是组件呈现效果和示例代码以及参数配置项说明

  • 示例代码和参数配置项说明可以通过编写 md 文档来实现
  • 组件呈现效果需要另外开发个 demo 组件来编写示例代码并运行

这意味着,封装一个组件,除了写文档,还需要再开发一个组件使用 demo,成本有些大,维护也麻烦

那么,有没有什么办法可以简化呢?

解决方案:自定义 md-loader

md-loader 是一个自定义的 webpack loader,用来解析 md 文件的,简单来说,它做了两件事:

  • 将 md 解析成 vue 组件,以便 vue 项目里可以直接将 md 当作 vue 组件使用
  • 自定义 md 语法 ::: demo,以便达到只需在 md 中编写组件示例代码,解析后的 vue 代码会自动将组件示例代码运行起来,呈现真实效果

有了 md-loader 的这两个能力,我们可以再基于 require.context 搞个自动挂载组件路由

这样一来,我们只要在每个组件目录下搞个 README.md 文档,里面贴上组件示例代码,然后运行项目,打开组件路由就可以像使用 element-ui 组件官网一样来翻看我们的组件文档了

我们还可以再集成 monaco-editor 就可以实现一个简易的在线编辑调试代码的功能

如:在线体验下

上面示例中的组件使用说明文档内容,包括呈现效果和示例代码,全程都只需要在 md 文档里编写即可,而无需额外编写其他 demo 代码,如:

# 全局弹窗 this.$rgDialog

为了避免每次使用弹窗时需要编写分散各处的片段代码(el-dialog 的模板代码,控制显隐变量,显示关闭函数等),提取封装了挂载在全局函数的弹窗 `this.$rgDialog`

直接在点击事件方法里即可完成弹窗的相关代码

## 使用示例

::: demo

```vue
<template>
<div>
<el-button type="primary" @click="showDialog">点击显示弹窗</el-button>
</div>
</template> <script>
import dialogContent from "@docs/使用说明.md";
export default {
data() {
return {};
},
mounted() {},
methods: {
showDialog() {
const rgDialog = this.$rgDialog({
props: {
title: "弹窗标题",
width: "80vw",
"close-on-click-modal": true
},
events: {},
content: dialogContent,
contentProps: {},
contentEvents: {
cancel: () => rgDialog.close()
}
}).show();
}
}
};
</script> <style lang="scss" scoped></style>
``` ::: ## options 参数说明 | 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ------------- | ----------------------------------- | ------ | ------ | ----------------------------------------------------------- |
| props | el-dialog 的 props 输入参数 | object | — | {width: '700px', top: '5vh', 'close-on-click-modal': false} |
| events | el-dialog 的输出事件,如 @opened 等 | string | — | — |
| content | 弹窗内容的 vue 组件 | object | — | — |
| contentProps | 弹窗内容 vue 组件的 props 输入参数 | object | — | — |
| contentEvents | 弹窗内容 vue 组件的输出事件 | object | — | — | ## 方法 `this.$rgDialog()` 返回的弹窗实例对象的方法: | 方法名 | 说明 | 参数 |
| ------ | -------- | ---- |
| show | 显示弹窗 | — |
| close | 关闭弹窗 | — |

md-loader 实现原理

这个 loader 是我前司一同事自己开发的,这是他的源码仓库和技术实现细节文档:

原理细节和源码可以移步到相关链接查看,这里简单概述下 md-loader 内部原理,一句话解释:

将 md 转成的 html 包裹到 vue 的 template 标签内,因此 md 可以直接被当作 vue 组件在代码里被引用,同时自定义扩展 md 的 ::: demo 语法,以便支持组件效果和示例代码可以呈现

loader 工作原理:

  1. 基于 markdown-it 系列插件将 md 转成 html
  2. 如果 md 里没有 ::: demo 场景,则直接将转成的 html 放到 vue 的 template 块里,交给 vue-loader 解析
  3. 如果有 ::: demo 场景,进入自定义解析 ::: demo 流程
    • 将 demo 里的 ```vue 代码块字符串化后放到 标签里的 highlight 插槽上。

      • 字符串化的过程做了系列代码的高亮、行号等显示处理
    • 再把 ```vue 代码块封装到单独的 vue 组件里,组件内部自动命名,然后给挂载到 标签里的 source 插槽上
    • 组件就可以用 highlight 插槽来把代码块呈现出来,同时用 source 插槽来引用 loader 生成的子组件,以达到代码块运行的效果

require.context 自动注册路由

// 递归遍历当前目录下为 .md 结尾的文件
const files = require.context(".", true, /\.md$/); files.keys().forEach((filePath) => {
// 省略根据文件路径名生成路由配置信息
// 生成路由配置相关信息,路由直接以组件目录名
const routerConfig = {
title: fileName,
path: `/${pathParts.join("/")}/${fileName}`,
component: files(filePath).default,
};
});

这样就不需要每新增一个组件, 都需要手动去注册路由信息了

注: 脚本可以借助 ChartGPT 完成, 描述好诉求就行

monaco-editor 在线代码编辑器

Vue 实现在线代码编辑和预览

小结

只需用 md 就能完成组件使用平台的搭建, 而无需再编写额外的 demo 等成本投入, 较低成本换来使用人的直观, 方便, 快捷的使用组件

自定义md-loader来简单高效的维护组件文档的更多相关文章

  1. SpringBoot整合Swagger2,再也不用维护接口文档了!

    前后端分离后,维护接口文档基本上是必不可少的工作.一个理想的状态是设计好后,接口文档发给前端和后端,大伙按照既定的规则各自开发,开发好了对接上了就可以上线了.当然这是一种非常理想的状态,实际开发中却很 ...

  2. [2013-03-14]使用wiki维护产品文档

    word文档作为产品文档的问题: word文档本身的设计是为了打印: word文档的编辑较为繁琐: 作为产品文档的word文档往往长达百页以上,难以维护,且容易分散注意力,不利于查阅: 没有一个简单易 ...

  3. python全栈开发day48-jqurey自定义动画,jQuery属性操作,jQuery的文档操作,jQuery中的ajax

    一.昨日内容回顾 1.jQuery初识 1).使用jQuery而非JS的六大理由 2).jQuery对象和js对象转换 3).jQuery的两大特点 4).jQuery的入口函数三大写法 5).jQu ...

  4. java简单实现用语音读txt文档

    最近比较无聊,随便翻着博客,无意中看到了有的人用VBS读文本内容,也就是读几句中文,emmm,挺有趣的,实现也很简单,都不需要安装什么环境,直接新建txt文件,输入一些简单的vbs读文本的代码,然后将 ...

  5. 高效查看MySQL帮助文档的方法

    在mysql的使用过程中, 可能经常会遇到以下问题: 某个操作语法忘记了, 如何快速查找? 如何快速知道当前版本上某个字段类型的取值范围? 当前版本都支持哪些函数?希望有例子说明.. 当前版本是否支持 ...

  6. 高效查看MySQL帮助文档的方法 (转)

    在mysql的使用过程中, 可能经常会遇到以下问题: 某个操作语法忘记了, 如何快速查找? 如何快速知道当前版本上某个字段类型的取值范围? 当前版本都支持哪些函数?希望有例子说明.. 当前版本是否支持 ...

  7. RAP, 高效前后端联调框架,接口文档管理工具

    RAP通过GUI工具帮助WEB工程师更高效的管理接口文档,同时通过分析接口结构自动生成Mock数据.校验真实接口的正确性,使接口文档成为开发流程中的强依赖.有了结构化的API数据,RAP可以做的更多, ...

  8. 用python批量生成简单的xml文档

    最近生成训练数据时,给一批无效的背景图片生成对应的xml文档,我用python写了一个简单的批量生成xml文档的demo,遇见了意外的小问题,记录一下. 报错问题为:ImportError: No m ...

  9. 【中文分词】简单高效的MMSeg

    最近碰到一个分词匹配需求--给定一个关键词表,作为自定义分词词典,用户query文本分词后,是否有词落入这个自定义词典中?现有的大多数Java系的分词方案基本都支持添加自定义词典,但是却不支持HDFS ...

  10. SDWebImage ReadMe.md文档简单说明

    SDWebImage ReadMe.md 文档 附:SDWebImage框架github下载地址:https://github.com/rs/SDWebImage 注1:该文章简单翻译了SDWebIm ...

随机推荐

  1. 「codeforces - 542D」Superhero's Job

    link. 容易发现,如果将 \(x\) 写作 \(\displaystyle \prod_{i = 1}^k p_i^{\alpha_i}\) 的形式,\(\displaystyle J(x) = ...

  2. Solution -「香港网络赛 2016」A+B Problem

    Description Link. 给出一个长度为 \(n\) 的序列 \(a\),问有序三元组 \((a_{i},a_{j},a_{k})\) 使得 \(i\neq j\neq k\) 且 \(a_ ...

  3. 命令行获取chrome版本的多个方法

    命令行获取chrome版本的多个方法 基于win10 测试 背景 在selenium的驱动安装中用webdriver_manager自动处理chromedriver是比较好的做法 webdriver_ ...

  4. C#学习笔记---异常捕获和变量

    异常捕获 使用异常捕获可以捕获出现异常的代码块,防止因为异常抛出造成的程序卡死的情况发生. try{}catch{}finally{}结构 //异常捕获 try { string str=Consol ...

  5. Linux 中如何安全地抹去磁盘数据?

    哈喽大家好,我是咸鱼 离过职的小伙伴都知道,离职的时候需要上交公司电脑,但是电脑里面有许多我们的个人信息(聊天记录.浏览记录等等) 所以我们就需要先把这些信息都删除,确保无法恢复之后才上交 即有些情况 ...

  6. POSIX 真的不适合对象存储吗?

    最近,留意到 MinIO 官方博客的一篇题为"在对象存储上实现 POSIX 访问接口是坏主意"的文章,作者以 S3FS-FUSE 为例分享了通过 POSIX 方式访问 MinIO ...

  7. Java Springbool敏感词过工具类滤

    Java Springbool敏感词过工具类滤 1. 功能描述利用前缀树这种数据结构,设计并开发出敏感词过滤工具. 2. 构建敏感词表resource/sensitive-words.txt 3. 敏 ...

  8. 解密Prompt系列19. LLM Agent之数据分析领域的应用:Data-Copilot & InsightPilot

    在之前的 LLM Agent+DB 的章节我们已经谈论过如何使用大模型接入数据库并获取数据,这一章我们聊聊大模型代理在数据分析领域的应用.数据分析主要是指在获取数据之后的数据清洗,数据处理,数据建模, ...

  9. UIPath变量和参数

    一. UIPath变量   变量(Variables),变量是所有编程语言中必不可少的部分.对于UIPath来说自然也是如此,其承载了我们RPA流程中数据传递的重要作用.对于接触过编程的开发者来说,变 ...

  10. Istio 网格的出口定义者:深入了解 Egress Gateway

    本文分享自华为云社区<Istio Egress 出口网关使用>,作者:k8s技术圈. 前面我们了解了位于服务网格内部的应用应如何访问网格外部的 HTTP 和 HTTPS 服务,知道如何通过 ...