• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    使用vue-markdown实现markdown文件预览

    发布者: 雪落无声 | 发布时间: 2025-6-16 07:40| 查看数: 140| 评论数: 0|帖子模式

    Vue-Markdown 是一个轻量级且高效的库,用于在Vue.js应用程序中渲染Markdown文本。它允许开发者以简洁的方式将Markdown的强大功能与Vue组件的灵活性相结合,提升开发效率和用户体验。vue-markdown 是一个基于 marked.js 的 Vue Markdown 插件。它是一个简单易用的 Markdown 解析器,可以方便地将 Markdown 文档解析为 HTML。它有如下特点:
    功能强大:支持 Markdown 语法的全部特性,例如标题、列表、链接等。
    易于使用:只需要在 Vue 组件中引入 vue-markdown 插件,并使用简单的模板语法即可实现 Markdown 的解析和渲染。
    高性能:基于 marked.js,性能优异,可以快速地解析和渲染大量的 Markdown 文档。
    扩展性强:支持自定义渲染规则,可以通过插件扩展功能,以满足更多的需求。

    一、插件使用


    1、插件说明

    vue-markdown插件的灵活性较好,支持直接传递Markdown字符串,或者通过绑定数据属性来动态渲染Markdown。此外,还可以自定义渲染规则,扩展或替换特定的Markdown语法,以满足个性化需求。在github上看了作者的源码,发现该插件也引入了markdown-it,并且支持大部分的markdown-it的插件,通过插件的引入即可使用。
    官方demo
    1)slots
    在组件中使用 vue-markdown 插件,可以在模板中添加 slots、props 和 events 的代码,如下:
    1. <template>
    2.   <vue-markdown :source="markdownText" >
    3.     <template v-slot:pre="">
    4.       <p>这是一个自定义的前置处理。</p>
    5.     </template>
    6.     <template v-slot:code="props">
    7.       <pre :class="'language-' + props.language">{{ props.code }}</pre>
    8.     </template>
    9.     <template v-slot:blockquote="">
    10.       <blockquote>{{ props.content }}</blockquote>
    11.     </template>
    12.   </vue-markdown>
    13. </template>
    复制代码
    2)配置参数
    参数名称类型默认值描述watchesArray
    1. ["source", "show", "toc"]
    复制代码
    是否开启监视数据变化,自动改变HTML。sourceString
    1. null
    复制代码
    要转换为 HTML 的 Markdown 字符串。showBoolean
    1. true
    复制代码
    是否显示转换后的 HTML 内容。htmlBoolean
    1. true
    复制代码
    是否允许解析 HTML 标签。默认为 false。xhtml-outBoolean
    1. true
    复制代码
    是否输出 XHTML 格式。
    1. <br></br>
    复制代码
    =>
    1. <br />
    复制代码
    breaksBoolean
    1. true
    复制代码
    是否将换行符解析为
    1. <br/>
    复制代码
    标签。
    1. \n
    复制代码
    =>
    1. <br>
    复制代码
    linkifyBoolean
    1. true
    复制代码
    是否将纯文本链接转换为链接。emojiBoolean
    1. true
    复制代码
    是否支持 emoji 表情。typographerBoolean
    1. true
    复制代码
    是否开启排版选项,例如引号转换、省略号转换等。lang-prefixString
    1. language-
    复制代码
    语法高亮语言前缀。quotesString
    1. “”‘’
    复制代码
    引用标记。中文:
    1. “”‘’
    复制代码
    , 德文:
    1. „“‚‘
    复制代码
    ,俄罗斯:
    1. «»„“
    复制代码
    table-classString
    1. table
    复制代码
    表格的 CSS 类名。task-listsBoolean
    1. true
    复制代码
    是否支持任务列表。tocBoolean
    1. false
    复制代码
    是否生成目录。toc-idString
    1. undefined
    复制代码
    生成目录的Idtoc-classString
    1. table
    复制代码
    目录的 CSS 类名。toc-first-levelNumber
    1. 2
    复制代码
    目录最顶层标题的级别,取值范围为 1-6。默认为 2。toc-last-levelNumber
    1. 'toc-first-level' + 1
    复制代码
    目录最后一层标题的级别,取值范围为 1-6。默认为5。toc-anchor-linkBoolean
    1. true
    复制代码
    在标题中启用自动锚链接toc-anchor-classString
    1. toc-anchor
    复制代码
    自定义锚类名toc-anchor-link-symbolString
    1. #
    复制代码
    目录中的锚点链接的符号。默认为 ‘#’。toc-anchor-link-spaceBoolean
    1. true
    复制代码
    目录中的锚点链接前的空格。toc-anchor-link-classString
    1. toc-anchor-link
    复制代码
    目录中的锚点链接的 CSS 类名。anchorAttributesObject
    1. {}
    复制代码
    锚点标签的属性。: '_blank’
    1. or
    复制代码
    rel: ‘nofollow’`prerenderFunction (String) String
    1. null
    复制代码
    在转换 HTML 前的回调函数。postrenderFunction (String) String
    1. null
    复制代码
    在转换 HTML 后的回调函数。3)事件
    vue-markdown 插件中,提供了以下两个事件:
    方法名称参数描述rendered显示的html元素(string)渲染结束后触发toc-rendered目录html元素(string)TOC目录渲染结束后触发,如果toc传的是
    1. false
    复制代码
    则不会触发
    2、安装
    1. // npm
    2. npm install vue-markdown
    3. // yarn
    4. yarn add vue-markdown --save
    复制代码
    3、使用
    1. <template>
    2.   <div>
    3.     <VueMarkdown :source="markdownText" />
    4.   </div>
    5. </template>

    6. <script>
    7. import VueMarkdown from 'vue-markdown'

    8. export default {
    9.   components: { VueMarkdown },
    10.   data() {
    11.     return {
    12.       markdownText: '# 这是第一个标题!'
    13.     }
    14.   }
    15. }
    16. </script>
    复制代码
    二、页面中渲染并添加目录

    在实际的项目开发过程中,为了方便定位与查阅,需要目录大纲,我们可以在旁边加上一个目录大纲,这里使用的el-tree进行目录的展示。

    1、HTML部分
    1. <template>
    2.     <div class="page-api" id="myElement">
    3.         <vue-markdown id="content" class="api-content" :source="markdownContent"></vue-markdown>
    4.         <div class="api-tree" id="tree">
    5.             <el-tree :data="tree" :default-expand-all="true" @node-click="handleNodeClick"></el-tree>
    6.         </div>
    7.     </div>
    8. </template>
    复制代码
    2、JS部分
    1. import VueMarkdown from 'vue-markdown';
    2. import markdownItAnchor from 'markdown-it-anchor';
    3. import markdownItToc from 'markdown-it-table-of-contents';
    4. import markdownItEmoji from 'markdown-it-emoji';
    5. import markdownItKatex from 'markdown-it-katex';
    6. export default {
    7.         data() {
    8.                 return {
    9.                         markdown: '# h1 Heading\n ## h2 Heading\n ### h3 Heading',
    10.                         markdownContent: '',
    11.                         tree: [],
    12.                         plugins: [markdownItAnchor, [markdownItToc, { includeLevel: [2, 3] }], markdownItEmoji, markdownItKatex]
    13.                 };
    14.         },
    15.         mounted() {
    16.                 this.loadMarkdownFile();
    17.         },
    18.         components: {
    19.                 VueMarkdown
    20.         },
    21.         methods: {
    22.                 async loadMarkdownFile() {
    23.                         try {
    24.                 //引入在public文件夹下的md文件
    25.                                 const response = await fetch('/XXXX.md');
    26.                                 const markdownText = await response.text();
    27.                                 this.markdownContent = markdownText;
    28.                                 this.$nextTick(() => {
    29.                                         this.catalogTree();
    30.                                 });
    31.                         } catch (error) {
    32.                                 console.error('Failed to load the Markdown file:', error);
    33.                         }
    34.                 },
    35.                 catalogTree() {
    36.                         const content = document.getElementById('content').children;
    37.                         var arr = [];
    38.                         let currentHightestLevel;
    39.                         let parentId;
    40.                         let index = 0;
    41.                         let nodeArr = [];
    42.                         let tree = [];
    43.                         for (let i = 0; i < content.length; i++) {
    44.                                 let header = content[i].localName;
    45.                                 //如果是标题进行下一步
    46.                                 if (/\b[h][0-9]\b/.test(header)) {
    47.                                         let ele = content[i]; // 直接使用DOM元素
    48.                                         let name = ele.textContent; // 获取元素的文本内容
    49.                                         ele.setAttribute('id', i); // 设置元素的ID
    50.                                        
    51.                                         let id = i;
    52.                                         if (index === 0 || header <= currentHightestLevel) {
    53.                                                 currentHightestLevel = header;
    54.                                                 parentId = id;
    55.                                         }
    56.                                         arr.push({
    57.                                                 id: id,
    58.                                                 label: name,
    59.                                                 parentId: parentId == id ? '0' : parentId
    60.                                         });
    61.                                         index++;
    62.                                 }
    63.                         }
    64.                         arr.forEach((item) => {
    65.                                 if (item.parentId === '0') {
    66.                                         tree.push(this.convertArrayToTree(arr, item));
    67.                                 }
    68.                         });
    69.                         this.tree = tree;
    70.                 },
    71.                 convertArrayToTree(arr, node) {
    72.                         for (let i = 0; i < arr.length; i++) {
    73.                                 if (arr[i].parentId === node.id) {
    74.                                         const res = this.convertArrayToTree(arr, arr[i]);
    75.                                         if (node.children) {
    76.                                                 node.children.push(res);
    77.                                         } else {
    78.                                                 node.children = [res];
    79.                                         }
    80.                                 }
    81.                         }
    82.                         return node;
    83.                 },
    84.                 handleNodeClick(data) {
    85.                         let anchorElement = document.getElementById(data.id);

    86.                         let scrollPosition = anchorElement.offsetTop - 20;

    87.                         let myElement = document.getElementById('myElement');
    88.                         myElement.scrollTo({
    89.                                 left: 0,
    90.                                 top: scrollPosition,
    91.                                 behavior: 'smooth'
    92.                         });
    93.                 }
    94.         }
    95. };
    复制代码
    3、CSS样式
    1. .page-api {
    2.         display: flex;
    3.         width: 100%;
    4.         height: 100%;
    5.         overflow-y: scroll;
    6.         background-color: #fff;
    7. }
    8. .api-tree {
    9.         position: fixed;
    10.         right: 20px;
    11.         top: 120px;
    12.         width: 250px;
    13.         height: 600px;
    14.         margin-right: 10px;
    15.         overflow-y: scroll;
    16.         /* text-overflow: ellipsis; */
    17.         z-index: 99;
    18.         .el-tree {
    19.                 background: none;
    20.                 color: #686868;
    21.                 .el-tree-node:focus > .el-tree-node__content,
    22.                 .el-tree-node__content:hover {
    23.                         background: none;
    24.                         color: rgb(24, 144, 255);
    25.                 }
    26.         }
    27. }
    28. .api-tree::-webkit-scrollbar {
    29.         width: 8px;
    30. }

    31. .api-content {
    32.         flex: 1;
    33.         width: 80%;
    34.         margin-left: 20px;
    35.         margin-right: 220px;
    36.         padding: 0 30px;
    37.         h2 {
    38.                 margin-left: 20px;
    39.                 margin-bottom: 10px;
    40.         }
    41.         h3 {
    42.                 margin-left: 25px;
    43.                 margin-bottom: 8px;
    44.         }
    45.         h4 {
    46.                 margin-left: 30px;
    47.                 margin-bottom: 5px;
    48.         }
    49.         li {
    50.                 margin-left: 40px;
    51.         }
    52.         code {
    53.                 border-radius: 2px;
    54.                 color: #ffaa7f;
    55.                 margin: 0 2px;
    56.                 padding: 3px 5px;
    57.                 white-space: pre-wrap;
    58.         }
    59.         table {
    60.                 border-collapse: collapse;
    61.                 border-spacing: 0;
    62.                 th,
    63.                 td {
    64.                         border: 1px solid #ddd;
    65.                         padding: 6px 13px;
    66.                         margin: 0;
    67.                 }
    68.         }
    69.         pre {
    70.                 background: rgba(0, 0, 0, 0.7);
    71.                 padding: 20px 30px;
    72.         }
    73. }
    74. .page-api::-webkit-scrollbar {
    75.         width: 8px;
    76. }
    77. /* 滚动条滑块样式 */
    78. .page-api::-webkit-scrollbar-thumb {
    79.         background-color: #888; /* 设置滑块背景颜色 */
    80.         border-radius: 4px; /* 设置滑块圆角 */
    81. }
    复制代码
    4、效果展示


    到此这篇关于使用vue-markdown实现markdown文件预览的文章就介绍到这了,更多相关vue预览markdown内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:https://www.jb51.net/javascript/339441g1s.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表