likes
comments
collection
share

Markdown文档-展示与美化方法

作者站长头像
站长
· 阅读数 12

本着简单开发使用

采用插件:vue-markdown-loader

地址链接:github.com/QingWei-Li/…

npm安装

使用 npm 安装 vue-markdown-loader 插件:

cnpm install vue-markdown-loader

我本次安装的版本:"vue-markdown-loader": "^2.5.0",

插件效果:生成组件式的代码,引用后直接使用

配置webpack

需要配置 webpack 来使用 vue-markdown-loader 插件。在 vue.config.js 文件中添加以下配置:

module.exports = {
 chainWebpack: config => {
    config.module
          .rule('md')
          .test(/\.md/)
          .use('vue-loader')
          .loader('vue-loader')
          .end()
          .use('vue-markdown-loader')
          .loader('vue-markdown-loader/lib/markdown-compiler')
          .options({
            raw: true
          });
       }
}

优化html结构

一般情况下,我们可以在选项中进行配置,但是由于我对此不够了解,所以没有在官方文档中找到相关方法。因此,我打算获取 DOM 并修改其 innerHTML。

添加结构

准备结构

首先,准备以下结构:

<div class="doc-container">
  <div class="markdown-body">
    <component :is="componentsName" ref="componentRef" />
  </div>
</div>

请注意:

  1. 必须添加 markdown-body 这个 class。
  2. 使用 <component is="Xxx" /> 来渲染组件。这是因为 vue-markdown-loader 会将 markdown 文件转换为 Vue 文件,直接渲染 markdown 文件就好了!此外,还可以在一个公共页面(例如 index)中获取 DOM,统一处理 innerHTML

导入文件

导入需要展示的 markdown 文件,例如:

import HeaderMd from '@/header/README.md';
import ButtonMd from '@/button/README.md';
......

markdown文件内容

随便整点花生米(markdown)文件内容,例如:

- # 按钮
- ## markDown的使用
- ### markDown的使用
- 你使用的是makeDown的文件
- ```js
- let a = 0
- ```
- ### markDown的使用
- 你使用的是makeDown的文件
- ```js
- let a = 0
- ```

得到的html渲染结构

Markdown文档-展示与美化方法

页面展示效果

Markdown文档-展示与美化方法

看的出来,这种怎么写都不会好看起来,如果h3pre标签包裹在一起变成卡片式的样式,那么看着要舒服很多。

接下来就开始进行优化结构。

优化结构

开始优化结构

1、先获取DOM

2、每一个markdown页面的DOM,利用new Map()根据key='pathName',存起来好一些。

如果路由下次进来,取出Map中的数据,直接插入到别的标签中,而不是再次的进入,重新获取DOM,重新优化标签,然而缺点就是,在文件中更新了markdown的信息,不能及时的同步到页面中,需要刷新一下,暂时没有想到其他好方法。

----------data----------------

componentRefMap: new Map(),

---------methods--------------

getComponentRef(pathName) {
    if (pathName !== '') {
      this.$nextTick(() => {
        this.componentRefMap.set(pathName, this.$refs.componentRef.$el);
        // 下面要说的优化标签
        this.optimizationTags(this.componentRefMap);
        // 下面要说的添加操作
        this.eventListenerTages();
      });
    }
},

优化标签

得益于结构的简单化,参考vant的vite.config配置,使用方法如下:

optimizationTags(dataMap, hasValue = false) {

let refContent = dataMap.get(this.pathName);

let group = refContent.innerHTML
  .replace(/<h1/g, ':::<h1')
  .replace(/<h2/g, ':::<h2')
  .replace(/<h3/g, ':::<h3')
  .split(':::');

let groupHtml = group
  .map((fragment) => {
    if (fragment.indexOf('<h3') !== -1) {
      h3Setioncount++;
      let fragmentHtml = `<div class="doc-card">${fragment}</div>`;
      return fragmentHtml;
    }
    return fragment;
  })
  .join('');
dataMap.get(this.pathName).innerHTML = groupHtml;
},

解释一下: 将 h1、h2 和 h3 标签分隔开,并存储在数组 group 中。然后,对数组进行处理,如果其中的片段包含 <h3 标签,就在外部添加一个包裹 div,并赋予其类名 doc-card。最后,将处理后的 HTML 内容重新赋值给对应的 DOM 元素。

看的出来 h1 h2 h3标签都被切开了,没记错的话,我们取一段解释,结构中展示了 h2+h3+pre+h1,那么切开就是,h2 h3+pre h1三个fragment,我们就可以针对h3所在的fragment进行处理。

展示效果

Markdown文档-展示与美化方法

这样我们就可以进行样式的书写了,我们也可以自定义更多自己喜欢的东西。

添加操作

类似地,我们可以在标签中添加操作,并进行相应的处理。例如,为每个 <pre> 标签添加一个操作按钮。

let group = refContent.innerHTML
          .replace(/<h1/g, ':::<h1')
          ......
          .replace(/<pre>/g, '<pre><div class="operate"><div class="copy">复制</div></div>')
          .split(':::');

把操作都放到operate类中,再获取DOM,进行操作就简单一点

复制操作

eventListenerTages() {
let nodeOperateArr = document.querySelectorAll(".operate");
    nodeOperateArr.forEach((nodeOperate) => {
      nodeOperate.onclick = (event) => {
      if (event.target.className == "copy") {
       // 复制操作
        let textInnerText = nodeOperate.nextSibling.innerText;
        // 复制操作的具体实现...
        ......
        alert("复制成功");
      }
    };
    });
},

上述代码通过获取所有具有类名 .operate 的 DOM 元素,为其添加点击事件监听器。当点击事件发生时,利用event.target.className获取到,你点击的子标签的类名。就可以根据需要执行相应的操作,例如复制文本内容。

使用nextSibling,轻松的拿下copy节点的下一个pre的节点内容

类比一下:操作的方式,也可以进行书写了

添加锚点

同样地,我们只需要添加锚点来实现页面内的平滑滚动。

optimizationTags(){
    ....
 let groupHtml = group
          .map((fragment) => {
          // 设计锚点的数据
          let h2Setioncount = 0;
          let h3Setioncount = 0;
            ......
            if (fragment.indexOf('<h2') !== -1) {
              h2Setioncount++;
              h3Setioncount = 0;
              let fragmentHtml = fragment.replace(/<h2/g, `<h2 id=${this.pathName}_${h2Setioncount}-${h3Setioncount}`);
              return fragmentHtml;
            }
            if (fragment.indexOf('<h3') !== -1) {
              h3Setioncount++;
              let fragmentHtml = `<div class="doc-card" id=${this.pathName}_${h2Setioncount}-${h3Setioncount}>${fragment}</div>`;
              return fragmentHtml;
            }
            return fragment;
          })
          .join('');
}

生成的结构:

Markdown文档-展示与美化方法

滑动的难处

由于我使用的是hash路由,传统的锚点#maodian方式在这种情况下不起作用,

例如: http://example.com/hello#top

而在我的情况下,URL的格式为http://example.com/#/hello#top,这种情况下top无法直接使用作为锚点。

为了解决这个问题,我们采用参数传递的方式,手动进行滚动操作。

通过获取URL中的查询参数section来指定滚动到的目标位置,然后使用JS的scrollIntoView()方法进行平滑滚动。

smoothScrollSection(valueSection) {
    this.$nextTick(() => {
      let value = valueSection || this.$route.query.section;
      try {
        let NodeSection = document.getElementById(value);
        NodeSection.scrollIntoView({ behavior: 'smooth' });
      } catch (error) {
        console.error("没有这个锚点");
        alert("请检查结构的正确性");
      }
    });
  },

上述代码用于实现平滑滚动至指定锚点的功能。根据提供的锚点值(或从路由参数中获取),通过 getElementById 方法获取对应的 DOM 元素,并使用 scrollIntoView 方法进行平滑滚动。


我说如果,你想在页面上点击操作,修改了页面url而页面不更新的效果,可以采用下面的方法

// 只是一个展示其他设置
const searchParams = new URLSearchParams(window.location.search);
// 修改section参数的值
searchParams.set('section', 'xxx');
const newUrl = '#' + this.$route.path + '?' + searchParams.toString();
window.history.replaceState({}, '', newUrl);

在上面的一顿操作下来,url变了,但是没有更新,我们就可以顺利的在下面使用定义好的滑动操作

this.smoothScrollSection('Xxxx_x_x');

这个是真的在动,是根据,你上面修改Url的锚点值,传入即可。

效果

Markdown文档-展示与美化方法

优化样式

需要安装

npm

cnpm install github-markdown-css

cnpm install highlight

导入

刚刚好,我把全部的markdown都经过index.vue文件,直接引入就行

import "github-markdown-css";
import "highlight.js/styles/github.css";

剩下的样式,可以根据喜好,自定义覆盖与修改。

<style lang="scss" scoped>
    // 自定义一下
    @import url(./markdownstyle.scss);
</style>

最终效果

Markdown文档-展示与美化方法

转载自:https://juejin.cn/post/7231018455242457144
评论
请登录