组件库中的示例代码是如何展示的呢?(一)

740 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

作为一名前端工程师,日常工作中免不了使用各种组件库。每次使用时,我都在想,这示例组件是怎么写的?
Pasted image 20221125075214.png

难道和我一样,也是将示例代码复制粘贴一份嘛?

于是,我就去深入地研究了一下,果然,只有我在使用这种质朴的做法。由于笔者工作中使用 Vue,很多 Vue 的组件库是基于 Vuepress 或 Vitepress 编写。所以,这里就以 Vuepress 的一个插件 Vuepress-plugin-demo-container 为例,深入研究一下其工作原理。

基本原理

首先,我们来看一下该插件的源码结构:

 src
  | - common                     // 工具函数、渲染函数、容器函数
  | - - | - container.js
  | - - | - render.js
  | - - | - util.js
  | - i18n                       // 国际化语言配置
  | 	| - default_lang.json    // 语言配置
  | - DemoBlock.vue              // 示例组件容器
  | - enhanceAppFile.js          // 注册组件
  | - index.js                   // 默认导出文件

我们从index.js文件出发,了解插件的整体思路:

/**
 * 提供 ::: demo xxx ::: 语法,用于构建 markdown 中的示例
 */
const path = require('path')
const renderDemoBlock = require('./common/render')
const demoBlockContainers = require('./common/containers')
module.exports = (options = {}, ctx) => {
  return {
    enhanceAppFiles: path.resolve(__dirname, './enhanceAppFile.js'),
    chainMarkdown(config) {
      config.plugin('containers')
        .use(demoBlockContainers(options))
        .end();
    },
    extendMarkdown: md => {
      const id = setInterval(() => {
        const render = md.render;
        if (typeof render.call(md, '') === 'object') {
          md.render = (...args) => {
            let result = render.call(md, ...args);
            const { template, script, style } = renderDemoBlock(result.html);
            result.html = template;
            result.dataBlockString = `${script}\n${style}\n${result.dataBlockString}`;
            return result;
          }
          clearInterval(id);
        }
      }, 10);
    }
  }
}

从 index.js 文件中,我们可以看出整体分为三部分:

  1. enhanceAppFiles:此选项接受指向增强文件的绝对文件路径或返回该路径的函数,你可以通过此选项做一些应用级别的配置。应用级别就是指安装一些附加的 Vue 插件、注册全局组件,或者增加额外的路由钩子等。在本插件中,就是指向了一个包裹示例demo、源码的组件,该组件通过 Vue.component 进行全局注册。
  2. chainMarkdown:使用 markdown-it-chain 修改内部的 markdown 配置。在本插件中主要用于识别 ::: demo 语法,构造 html 字符串。
  3. extendMarkdown:修改用于 markdown 文件渲染的配置。在本插件中,主要用于处理上一步得到的 html 字符串,并通过 vue-template-compiler 将其编译为 render Function

工作流程

从以上分析,我们也可以得知该插件的工作流程为:

  1. 识别 :::demo 语法,得到 html 字符串
  2. 处理 html 字符串,得到渲染函数
  3. 通过 vue-loader 处理渲染函数,最终渲染到页面上

更详细的流程图如下所示:

xiezuo20221125-152555.png

总结

本篇文章梳理了vuepress-plugin-demo-container的整体工作流程。接下来会详细论述每一步的流程,真正理解其背后的原理。