最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 如何实现企业级组件库文档--浅谈ElementUI的md-loader(1)

    正文概述 掘金(弗兰肯斯坦)   2021-03-26   1161

    预计阅读时间: 6分钟

    前言

    一个好的组件库,其文档必然是易读且易于维护的。 element-ui 作为一个优秀的组件库显然做到了这一点。 element-ui 的官网是使用 vue 开发的,将官方仓库的代码 clone 到本地运行,就可以在本地构建 element-ui 的官网。值得注意的是,根据源码中 vue-router 的路由信息,element-ui 的所有组件文档页引入的并不是一个.vue文件,而是一个 .md 文件。 打开其中的一个.md文件( examples/docs/zh-CN/backtop.md ),发现 element-uimarkdown 语法和 vue 代码结合到了一起,官网中的组件文档页也是由这些文件生成 ?

    ## Backtop 回到顶部
    
    返回页面顶部的操作按钮
    
    ### 基础用法
    
    滑动页面即可看到右下方的按钮。
    :::demo
    
    ​```html
    <template>
      Scroll down to see the bottom-right button.
      <el-backtop target=".page-component__scroll .el-scrollbar__wrap"></el-backtop>
    </template>
    ​```
    :::
    

    这种做法节省了大量的维护成本。跟写页面相比,写markdown 显然省事多了。那么 element-ui 是如何做到将一个 .md 文件生成官网中独立的页面呢?

    从webpack入手

    我们可以在 build/webpack.demo.js 文件中看到 element-uiwebpack 配置,在其中我们可以找到 element-ui 对于 .md 文件的处理。

    
       {
            test: /\.md$/,
            use: [
              {
                loader: 'vue-loader',
                options: {
                  compilerOptions: {
                    preserveWhitespace: false
                  }
                }
              },
              {
                loader: path.resolve(__dirname, './md-loader/index.js')
              }
            ]
          }
    
    

    根据这段配置,webpack 一旦遇到以 .md 结尾的文件,就会读取文件中的内容,将这些内容传入相应的 loader 中进行处理。由于 loader 的调用顺序是从下往上的,所以会先调用 md-loader,然后将 md-loader 处理好的内容传入 vue-loader 中 。只要传入 vue-loader 中的内容符合 vue 的单文件组件的规范,就可以当做一个 vue 文件处理。这样一来,我们就将 .md 文件处理为 vue 文件了。扩展开来,只要我们配置好相应的 loader ,不只是 .md 文件,任意的文件都可以通过 vue-loader 进行处理。

    经过以上的分析,我们可以得知,在整个过程中最关键的部分就是 md-loader 了。那么在 md-loader 中, element-ui 是如何做到将 .md 文件处理为 vue 格式的呢?接下来我们可以打开 md-loader 的入口文件一起了解( md-loader/index.js )。

    md-loader地址

    md-loader

    首先我们需要了解 element-ui 对于 .md 文件的处理思路,主要分为两步:

    1. .md 文件转换为普通的 html

    2. 将转换后的 html 代码处理为 vue 格式。

    关于第一步有现成的工具可以实现。element-ui 使用的是 markdown-it。幸运的是这个工具有在线demo,我们可以直接将 markdown 代码复制到其中查看解析结果。在这里我们使用 element-uibutton 组件文档作为示例( examples/docs/zh-CN/button.md )。将该文件复制到在线demo中,即可看到效果。注意右上角的三个标记,分别表示了查看的三种内容:

    1. html,可以查看 markdown 转换后的页面效果。

    如何实现企业级组件库文档--浅谈ElementUI的md-loader(1)

    1. source,可以查看 markdown 转换后生成的 html 代码。

    如何实现企业级组件库文档--浅谈ElementUI的md-loader(1)

    3.debug,可以查看 markdown 转换后生成的 tokens 数组,后面会用到。

    如何实现企业级组件库文档--浅谈ElementUI的md-loader(1)

    有了 markdown-it 插件的帮助,现在我们已经可以将 .md 文件转换为普通的 html 了。以上的过程如果用代码描述的话就是:

    npm i markdown-it 
    
    var md = require('markdown-it')();
    var result = md.render('button.md中的内容');
    

    没错只有三行 ?

    当然,转换后的代码不可能和我们的需求完全一致, element-ui 在转换的过程中也进行了其他的处理。这些配置都放在了 config.js 中。

    const md = require('./config');
    
    module.exports = function(source) {
      const content = md.render(source);
    }
    

    这些配置中主要包括标题锚点和自定义代码块。关于锚点,细心的朋友可以发现,当你将鼠标放在 element-ui 文档的标题上时,会出现一个符号标记,这就是锚点了。

    如何实现企业级组件库文档--浅谈ElementUI的md-loader(1)

    锚点作用是点击之后可以跳转到页面的对应位置。虽然 element-ui 的文档中的标题设置了锚点,但是并没有对应的页面大纲。所以只能通过点击标题触发锚点 ? ( 在 Element Plus 中优化了这个问题 )。

    另一个配置是自定义代码块,这是一个很重要的配置。我们可以观察到文档中的有一段内容被 :::demo 标记包裹了起来

    ::: demo
    xxxx
    xxxx
    :::
    

    很显然这个标记不属于正文里的内容,这里使用了 markdown-it 的一个插件,名叫 markdown-it-container。这个插件的作用是获取标记内的代码( :::demo )并返回自定义内容。这个过程就类似于 JavaScriptreplace 方法。

    这一段的代码在 build/md-loader/container.js 中。

    const mdContainer = require('markdown-it-container');
    
    module.exports = md => {
      md.use(mdContainer, 'demo', {
        // 验证是否存在代码块标记
        validate(params) {
          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>
            ${description ? `<div>${md.render(description)}</div>` : ''}
            <!--element-demo: ${content}:element-demo-->
            `;
          }
          return '</demo-block>';
        }
      });
    
      md.use(mdContainer, 'tip');
      md.use(mdContainer, 'warning');
    };
    
    

    其中的render 函数返回的 <demo-block>element-ui 中的用于 demo 展示的组件,暂时不用关心。这段代码中最令人费解的部分就是这个 tokens 参数了,这个参数代表的是什么呢?这就要回到我们最开始的在线demo中的 debug 内容了。从中我们可以看到 tokens 是一个数组,里面有一系列的 token 对象,用于描述如何生成 html 标签。token 对象的每一个属性都有各自的意义,如上述代码中的 info( 代码块中的内容 ),nesting( 判断标签是否闭合,1 代表标签打开标志,-1 代表标签关闭标志 )。具体可以查看 markdown-it 中文文档,里面还有对 markdown-it 更详尽的介绍。

    经过以上的步骤之后,我们终于拿到了一段经过我们转化后的代码了。

    这就是 md-loader 的前三行的内容?

    const md = require('./config');
    
    module.exports = function(source) {
      const content = md.render(source);
    }
    

    没错,整篇文章到现在,我们终于讲完了md-loader入口文件的前三行,大致了解了 content 变量里面的内容了,yeah!

    不过别着急,万事开头难。踏出第一步,才会有更多可能。

    总结

    我们现在已经可以将 .md 文件转换为 html 了。下一篇文章中,我们再一起聊聊如何将转换后的 html 代码处理为 vue 格式。

    如果这篇文章对你有所帮助,或者有所启发的话,求关注!求点赞!各位的支持和认可,就是我写作的最大动力?


    起源地下载网 » 如何实现企业级组件库文档--浅谈ElementUI的md-loader(1)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元