如何优雅的使用Vuepress编写组件示例(下)👈

简介: 如何优雅的使用Vuepress编写组件示例(下)👈

前言✍️


  • 最近在搭自己的组件库,关于文档用的是Vuepress
  • 官网在文档说明展示组件示例的方法有很多种,但种种都不合心意
  • 通过查阅网上的资料和Element的源码找出了我认为的一种最优解,借此机会分享一下
  • 该篇主要是具体的实现,如果想看分析的可以看到如何优雅的使用Vuepress编写组件示例(上)


实际效果✔️


先把最后的成品发出来给大家看看


李性分析🙋‍♂️


在上篇中分析归纳了一下具体的步骤(如下),接下来我们就来具体的实现一下

  • 第一步构建一个通用组件用于接收代码块来展示demo并且统一样式
  • 第二步设定一个Markdown自定义容器来编写demo代码
  • 第三步把自定义容器转化成之前构建的通用组件,这样就可以在md使用自定义容器来实现上文效果
  • 第四步扩展markdown渲染方法使我们输入的代码块可以输出内容为符合Vue Template语法的代码块
  • 第五步变成了vue代码后交由Vuepressvue-loader处理编译为文档


干就完了👊


构建组件📦

docs
├─ .vuepress
│  ├─ components
│  │  └─ demoBlock.vue
│  ├─ config.js
│  └─ enhanceApp.js
└─ component
   └─ basic
      └─ button.md
复制代码
  • 因为Vuepress可以自动识别components里面的组件并注册所以我们在里面建一个通用组件demoBlock用于展示demo
  • 参考了Element的通用组件后观察到这个组件主要由三部分组成:组件示例描述组件代码块
/* demoBlock.vue */
<template>
  <div class="block">
    <div class="demo-content">
      <!-- 插入组件 -->
      <slot name="demo"></slot>
    </div>
    <div class="meta" ref="meta">
      <div class="description">
        <!-- 插入描述信息 -->
        <slot name="description"></slot>
      </div>
      <div class="code-content">
        <!-- 插入代码块 -->
        <slot name="source"></slot>
      </div>
    </div>
  </div>
</template>
复制代码
  • 以上是一个简陋版的通用组件加上了简陋的样式,里面包含了三个插槽分别是组件示例描述组件代码块,这样我们就可以通过在mdvue的时候根据特别的插槽来组装我们的组件示例


创建自定义容器🧺

对于自定义组件我们可以使用markdown-it-container 参考官网构建

/* containers.js */
const mdContainer = require('markdown-it-container');
module.exports =md => {
    //将markdown-it-container插件加载到当前的解析器实例中
    md.use(mdContainer, 'demo', {
      validate(params) {
        //函数在开始标记后验证尾部,成功时返回true
        return params.trim().match(/^demo\s*(.*)$/);
      },
      render(tokens, idx) {
        //渲染器函数
        const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
        if (tokens[idx].nesting === 1) {
          const description = m && m.length > 1 ? m[1] : '';
          // opening tag
          return `<demo-block>
                  <div slot="demo">组件demo</div>
                  <div slot="description">${description}</div>
                  <div slot="source">代码块</div>`
        } else {
          // closing tag
          return `</demo-block>`;
        }
      }
    });
  }
复制代码

markdown-it-container支持两个参数,第一个是自定义容器的名字,第二个是一些选项

  • name - 自定义容器的名字
  • options:
  • validate - 可选,打开标记后验证尾部的功能,true成功时应返回
  • render - 可选,用于打开/关闭标记的渲染器函数
  • marker - 可选 ( :),在分隔符中使用的字符

render方法中也有两个参数

  • tokens  (Array) -- token 们的列表
  • idx  (Number) -- 用来渲染的 token 的索引

值得一提的是token的两个属性

  • info  -- 三个反引号后面跟的那个字符串
  • nesting -- 标签状态: 1表示打开 0表示自动关闭 -1表示正在关闭

在选项中的render可以对自定义的容器做渲染处理,像上面我就让识别到demo的自定义容器渲染成这个格式,那么我们在md文件输入自定义容器时就会找到对应的组件进行渲染

创建完自定义容器后我们要组装到Vuepress的配置中,Vuepress自带了chainMarkdown来修改内部的markdown配置,具体的配置操作可以参考配置插件

/* config.js */
module.exports = {
  title: 'Zylw-Ui',
  description: '开始你的组件化之旅吧~',
  ...
  plugins: [
    [
      require('./md-loader')
    ]
  ]
  ...
}
复制代码
/* index.js */
const demoBlockContainers = require('./common/containers')
module.exports = () => {
  return {
    chainMarkdown(config) {
      //修改内部的 markdown 配置
      config // 增加额外的插件markdownContainers
        .plugin('markdownContainers')
        .use(demoBlockContainers)
        .end();
    }
  }
}
复制代码

尝试在md文件中使用后效果就出来了

此时的结构是这样的

docs
├─ .vuepress
│  ├─ components
│  │  └─ demoBlock.vue
│  ├─ config.js
│  ├─ enhanceApp.js
│  └─ md-loader
│     ├─ common
│     │  └─ containers.js
│     └─ index.js
└─ component
   └─ basic
      └─ button.md
复制代码


分别渲染💞


大体效果架子出来了之后,我们就要考虑如何将自定义容器里的内容分别输出到组件位置代码块位置,一个典型的单文件组件包括三块:templatescriptstyle,那么接下的重点就是如何拼凑出templatescript的内容

我们可以参考element的做法,由于代码太长,先放上Element的源码可以一起食用可以看到Element在渲染的时候加入了一个占位符来接受我们的代码块,再通过编译的时候对这个注释块进行处理就可以分别转化到templatescriptstyle

这时我们就要改写一下我们的结构(此代码灵感来自Demo Container

/* containers.js */
const mdContainer = require('markdown-it-container');
module.exports =md => {
    //将markdown-it-container插件加载到当前的解析器实例中
    md.use(mdContainer, 'demo', {
      validate(params) {
        //函数在开始标记后验证尾部,成功时返回true
        return params.trim().match(/^demo\s*(.*)$/);
      },
      render(tokens, idx) {
        //渲染器函数
        const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
        if (tokens[idx].nesting === 1) {
          const description = m && m.length > 1 ? m[1] : '';
          const content = tokens[idx + 1].type === 'fence' ? tokens[idx + 1].content : '';
          return `<demo-block>
            <template slot="demo"><!--pre-render-demo:${content}:pre-render-demo--></template>
            ${description ? `<div slot="description">${md.render(description).html}</div>` : ''}
            <template slot="source">
          `;
        }
        return `</template></demo-block>`;
      }
    })
  }
复制代码
  • containers.js截取类型为fence的代码块放到占位符中
  • 通过render.js对占位符的内容进行处理 具体代码

  • 利用VuepressextendMarkdown API 继续拓展了其内部的markdown对象,修改内部用于渲染markdown文件的 markdown-it实例的配置
/* index.js */
const renderDemoBlock = require('./common/render')
module.exports = () => {
  return {
    ...
    extendMarkdown: md => {
      //修改内部用于渲染 markdown 文件的 markdown-it实例的配置
      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);
    }
  }
}
复制代码
  • 这样一个简陋的demo就大功告成啦!!!对比之前冗余写法是不是方便特别多呢,接下来只需要在demoBlock.vue更改属于自己的样式就可以啦

docs
├─ .vuepress
│  ├─ components
│  │  └─ demoBlock.vue
│  ├─ config.js
│  ├─ enhanceApp.js
│  └─ md-loader
│     ├─ common
│     │  ├─ render.js
│     │  ├─ util.js
│     │  └─ containers.js
│     └─ index.js
└─ component
   └─ basic
      └─ button.md
复制代码


写在最后👋


  • 当然如果不想自己重新配一个自定义容器的话也是有现成的插件的Demo Container
  • 本文的分析思路灵感也是借鉴于这个插件,对于一些源码的分析也是看了这位博主的插件才受益匪浅
  • 总的来说组件示例的呈现方式有很多,但是目前为止我觉得最好的是这种,通过markdown-it-container自定义容器的方法结合vue-template-compiler将代码片段转换成组件,不同的文档编辑器可能有不同的办法但原理都是相同的要么通过自身支持的插件进行配置要么通过Webpack进行配置
  • 通过这次自己尝试配置也深入理解了一些markdownhtml的一些原理,所以还是那句话多看源码真的很有用
  • 如果您觉得这篇文章有帮助到您的的话不妨🍉关注+点赞+收藏+评论+转发🍉支持一下哟~~😛


参考👈


谈谈 Element 文档中的 Markdown 解析

使用 markdown-it 解析 markdown 代码

Demo Container插件

Vuepress文档

Element UI


往期精彩🌅


Vue 3.0到底怎么变快?🚀

如何优雅的使用Vuepress编写组件示例(上)👈

手牵手🧑‍🤝‍🧑学习Gulp不用愁

为了方便,我改了别人的轮子😅

相关文章
|
敏捷开发 数据可视化 持续交付
带你读《SAFe 4.5参考指南:面向精益企业的规模化敏捷框架 》之一:SAFe基础
SAFe精益–敏捷领导者是终身学习者和老师,他们通过理解和展示精益–敏捷思维、SAFe原则和系统思考,帮助团队构建更好的系统。本书提供了一套在企业的投资组合、价值流、项目群和团队各个层面的完整的工作指南,包括构成框架的各种角色、活动和工件,以及价值观、理念、原则和实践的各种基本要素,并针对SAFe 4.5和SAFe 4.6进行了更新。
|
缓存 JavaScript 前端开发
mapbox没有token/token失效,地图闪烁后变空白,报错Error: A valid Mapbox access token is required to use Mapbox GL JS.
本博客介绍了mapbox如何去除token验证,暴力破解mapbox的token验证机制。一劳永逸解决mapbox地图闪现一下然后变成空白,报错Error: A valid Mapbox access token is required to use Mapbox GL JS.的方法,还介绍了类似问题的具体解决思路。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
467 25
|
JavaScript
js计算时间差,包括计算,天,时,分,秒
js计算时间差,包括计算,天,时,分,秒
1305 16
|
人工智能 自然语言处理 程序员
5个小妙招,通义灵码“一键治愈”你的代码问题
目前通义灵码支持 DeepSeek 满血版 V3 和 R1 模型,并内置 Qwen2.5-max 以及 QwQ-plus 模型,让研发体验焕新升级。
|
人工智能 安全 算法
多端融合,打造最优落地效果的多模态百炼
本次分享由阿里云智能集团飞天实验室资深产品专家江潇和科学家胡露露主讲,介绍了多端融合的多模态百炼产品。内容涵盖多模态模型的优化、生产力和产品力建设、RAG能力升级、终端大模型场景探索、内容安全和生态应用等方面。百炼已支持多模态模型调用,提升了模型效果和应用效果,并在安全性、模型优化和终端部署上取得了显著进展。
|
Java 数据库连接 mybatis
Mybatis mapper动态代理解决方案
该文介绍了Mybatis中使用Mapper接口的方式代替XML配置执行SQL。Mapper接口规范包括:namespace与接口类路径相同,select ID与接口方法名一致,parameterType和方法参数类型匹配,resultType与返回值类型一致。实现过程中,需配置Mapper.xml,编写Mapper.java接口,并在Mybatis-config.xml中设置。测试类中,通过SqlSession的getMapper方法获取接口的动态代理对象,调用方法执行SQL。
673 0
|
安全 定位技术 网络安全
禁止应用在模拟器上运行的方案及app安全问题
禁止应用在模拟器上运行的方案及app安全问题
1780 1
|
开发工具 IDE 开发者
通义灵码安装教程
https://developer.aliyun.com/topic/lingma/activities/202405?taskCode=16245&recordId=c0836910524e8a25109e3abeba50938d#/?utm_content=m_fission_1 「通义灵码推荐官,喊你高效 AI 编码,还有iPhone15、机械键盘、双肩包等福利可领。」

热门文章

最新文章