记一次使用vue-markdown在vue中解析markdown格式文件,并自动生成目录大纲
先上效果图

如图所示,在网页中,能直接解析markdown文档,并且生成目录大纲,也支持点击目录标题跳转到对应栏目中,下面就来讲讲是如何实现此功能的。
1、下载vue-markdown
yarn add vue-markdown
2、在页面中渲染markdown文件
<template><div><VueMarkdownclass="api-content":source="markdownContent"id="content"/></div>
</template><script>
import VueMarkdown from "vue-markdown";export default {components: {VueMarkdown,},data() {return {markdownContent: "",};},mounted() {this.loadMarkdownFile();},methods: {async loadMarkdownFile() {try {// api.md文件存放在根目录下的public文件夹中const response = await fetch("/api.md");const markdownText = await response.text();this.markdownContent = markdownText;} catch (error) {console.error("Failed to load the Markdown file:", error);}}, },
};
</script>
此时,打开浏览器查看,页面中已经正常渲染markdown文件了。
3、生成目录大纲
现在,我们需要有目录大纲方便我们查看文档。我的思路是,首先拿到markdown文件的html结构,然后找到所有H1-H5的标题标签,并给这些标签设置id,生成一个新数组,通过这个数组生成目录结构,说干就干。
//html部分<div class="api-tree" id="tree"><el-tree:data="tree":default-expand-all="true"@node-click="handleNodeClick"></el-tree>
</div>// js部分
catalogTree() {const content = document.getElementById("content").children;var arr = [];let currentHightestLevel;let parentId;let index = 0;for (let i = 0; i < content.length; i++) {let header = content[i].localName;if (/\b[h][0-9]\b/.test(header)) {let ele = $(content[i]);let name = ele.text();// 设置idele.attr("id", i);let id = i;if (index === 0 || header <= currentHightestLevel) {currentHightestLevel = header;parentId = id;}arr.push({id: id,label: name,parentId: parentId == id ? "0" : parentId,});index++;}}const tree = [];arr.forEach((item) => {if (item.parentId === "0") {tree.push(this.convertArrayToTree(arr, item));}});this.tree = tree;
},
convertArrayToTree(arr, node) {for (let i = 0; i < arr.length; i++) {if (arr[i].parentId === node.id) {const res = this.convertArrayToTree(arr, arr[i]);if (node.children) {node.children.push(res);} else {node.children = [res];}}}return node;
},
handleNodeClick(data) {let anchorElement = document.getElementById(data.id);if (anchorElement) {anchorElement.scrollIntoView({behavior: "smooth",block: "end",});}
},
4、大功告成,最后,附上全部代码,带css样式
<template><div class="page-api" id="myElement"><div class="api-tree" id="tree"><el-tree:data="tree":default-expand-all="true"@node-click="handleNodeClick"></el-tree></div><VueMarkdownclass="api-content":source="markdownContent"id="content"/></div>
</template><script>
import VueMarkdown from "vue-markdown";
import $ from "jquery";export default {components: {VueMarkdown,},data() {return {markdownContent: "",tree: [],};},mounted() {this.loadMarkdownFile();},methods: {async loadMarkdownFile() {try {const response = await fetch("/api.md");const markdownText = await response.text();this.markdownContent = markdownText;this.$nextTick(() => {this.catalogTree();});} catch (error) {console.error("Failed to load the Markdown file:", error);}},catalogTree() {const content = document.getElementById("content").children;var arr = [];let currentHightestLevel;let parentId;let index = 0;for (let i = 0; i < content.length; i++) {let header = content[i].localName;if (/\b[h][0-9]\b/.test(header)) {let ele = $(content[i]);let name = ele.text();// 设置idele.attr("id", i);// let id = ele.children("a").attr("id");let id = i;if (index === 0 || header <= currentHightestLevel) {currentHightestLevel = header;parentId = id;}arr.push({id: id,label: name,parentId: parentId == id ? "0" : parentId,});index++;}}const tree = [];arr.forEach((item) => {if (item.parentId === "0") {tree.push(this.convertArrayToTree(arr, item));}});this.tree = tree;},convertArrayToTree(arr, node) {for (let i = 0; i < arr.length; i++) {if (arr[i].parentId === node.id) {const res = this.convertArrayToTree(arr, arr[i]);if (node.children) {node.children.push(res);} else {node.children = [res];}}}return node;},handleNodeClick(data) {let anchorElement = document.getElementById(data.id);let scrollPosition = anchorElement.offsetTop - 20;let myElement = document.getElementById("myElement");myElement.scrollTo({left: 0,top: scrollPosition,behavior: "smooth",});// if (anchorElement) {// anchorElement.scrollIntoView({// behavior: "smooth",// block: "end",// });// }},},
};
</script><style lang="scss">
.page-api {display: flex;height: 100%;overflow-y: scroll;.api-tree {position: fixed;left: 20px;top: 120px;width: 200px;height: calc(100% - 160px);overflow-y: scroll;z-index: 99;.el-tree {background: none;color: #fff;.el-tree-node:focus > .el-tree-node__content,.el-tree-node__content:hover {background: none;color: rgb(24, 144, 255);}}}.api-content {flex: 1;margin-left: 220px;padding: 0 30px;color: rgba(255, 255, 255, 0.75);h3 {margin-left: 25px;}code {border-radius: 2px;color: #e96900;margin: 0 2px;padding: 3px 5px;white-space: pre-wrap;}table {border-collapse: collapse;border-spacing: 0;th,td {border: 1px solid #ddd;padding: 6px 13px;margin: 0;}}pre {background: rgba(0, 0, 0, 0.7);padding: 20px 30px;}}
}
</style>
相关文章:
记一次使用vue-markdown在vue中解析markdown格式文件,并自动生成目录大纲
先上效果图 如图所示,在网页中,能直接解析markdown文档,并且生成目录大纲,也支持点击目录标题跳转到对应栏目中,下面就来讲讲是如何实现此功能的。 1、下载vue-markdown yarn add vue-markdown 2、在页面中渲染markdo…...
力扣每日一题35:搜索插入的位置
题目描述: 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5…...
Iptabels的相关描述理解防火墙的必读文章
Iptabels是与Linux内核集成的包过滤防火墙系统,几乎所有的linux发行版本都会包含Iptables的功能。如果 Linux 系统连接到因特网或 LAN、服务器或连接 LAN 和因特网的代理服务器, 则Iptables有利于在 Linux 系统上更好地控制 IP 信息包过滤和防火墙配置。…...
Maven 构建项目测试
在上一章节中我们学会了如何使用 Maven 创建 Java 应用。接下来我们要学习如何构建和测试这个项目。 进入 C:/MVN 文件夹下,打开 consumerBanking 文件夹。你将看到有一个 pom.xml 文件,代码如下: <project xmlns"http://maven.apa…...
机器学习 - 似然函数:概念、应用与代码实例
目录 一、概要二、什么是似然函数数学定义似然与概率的区别重要性举例 三、似然函数与概率密度函数似然函数(Likelihood Function)定义例子 概率密度函数(Probability Density Function, PDF)定义 区别与联系 四、最大似然估计&am…...
LeetCode 热题 100-49. 字母异位词分组
题目描述 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“bat”],[“n…...
TensorFlow入门(十九、softmax算法处理分类问题)
softmax是什么? Sigmoid、Tanh、ReLU等激活函数,输出值只有两种(0、1,或-1、1或0、x),而实际现实生活中往往需要对某一问题进行多种分类。例如之前识别图片中模糊手写数字的例子,这个时候就需要使用softmax算法。 softmax的算法逻辑 如果判断输入属于某一个类的概率大于属于其…...
刷题用到的非常有用的函数c++(持续更新)
阅读导航 字符串处理类一、stoi()(将字符串转换为整数类型)二、to_string()(将整数类型转换为字符串类型)三、stringstream函数(将一个字符串按照指定的分隔符进行分词) 字符串处理类 一、stoi()ÿ…...
黑客技术(网络安全)——自学思路
如果你想自学网络安全,首先你必须了解什么是网络安全!,什么是黑客!! 1.无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面性,例如 Web 安全技术,既有 Web 渗透2.也有 Web 防…...
lNmp安装:
一、LNMP LNMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件, 能够提供动态Web站点服务及其应用开发环境。LNMP是一个缩写词,具体包括Linux操作系统、nginx网站服务器、MySQL数据库服务器、 PHP(或…...
Fisher辨别分析
问题要求 在UCI数据集上的Iris和Sonar数据上验证算法的有效性。训练和测试样本有三种方式(三选一)进行划分: (一) 将数据随机分训练和测试,多次平均求结果 (二)K折交叉验证 &…...
【Zookeeper专题】Zookeeper选举Leader源码解析
目录 前言阅读建议课程内容一、ZK Leader选举流程回顾二、源码流程图三、Leader选举模型图 学习总结 前言 为什么要看源码?说实在博主之前看Spring源码之前没想过这个问题。因为我在看之前就曾听闻大佬们说过【JavaCoder三板斧:Java,Mysql&a…...
机器学习之自训练协同训练
前言 监督学习往往需要大量的标注数据, 而标注数据的成本比较高 . 因此 , 利用大量的无标注数据来提高监督学习的效果有着十分重要的意义. 这种利用少量标注数据和大量无标注数据进行学习的方式称为 半监督学习 ( Semi…...
ubuntu 通过apt-get快速安装 docker
在使用 apt-get 安装 Docker 之前,你需要确保你的系统已经准备好并且已经更新了软件包列表。以下是在 Ubuntu 系统上使用 apt-get 安装 Docker 的步骤: 更新软件包列表: sudo apt-get update 安装依赖软件包,以确保可以通过 HTTPS 使用存储库: sudo apt-get install apt-t…...
C++医院影像科PACS源码:三维重建、检查预约、胶片打印、图像处理、测量分析等
PACS连接DICOM接口的医疗器械(如CT、MRI、CR、DR、DSA、各种窥镜成像系统设备等),实现图像无损传输,实现DICOM胶片打印机回传打印功能,支持各种图像处理,可以进行窗技术调节,与登记台管理系统共…...
企业聊天应用程序使用 Kubernetes
1. 客户端-服务器工作流程 客户端:在我们的架构中,客户端可以分为三种类型:iOS 和 Android 移动应用程序以及 Web 聊天。移动应用程序首先通过 API 网关服务与服务器进行通信,其中客户端会生成一个访问令牌,该令牌将授…...
记录用命令行将项目打包成war包
记录用命令行将项目打包成war包 找到项目的pom.xml 在当前路径下进入cmd 输入命令 mvn clean package 发现报错了 Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war (default-war) on project MMS: Error assembling WAR: webxml attribute is req…...
Linux基础知识笔记
Linux基础知识笔记 介绍/dev/null作用2>&1作用 介绍 记录linux基础知识,持续更新中… /dev/null作用 /dev/null 是一个特殊的设备文件,可以将数据重定向到这个文件中,从而实现将输出或错误信息丢弃的效果。在 Linux 系统中…...
Laya3.0 入门教程
点击play箭头 点击右边的开发者工具 就会弹出 chrome的调试窗口 然后定位到你自己的ts文件 直接在ts里断点即可 不需要js文件 如何自动生成代码? 比如你打开一个新项目 里面显示的是当前场景 只需要点击 UI运行时 右边的框就可以了 他会自动弹窗提示你 创建一个文…...
3D全景虚拟样板间展销系统扩展用户市场范围
VR样板间,能够真实还原现场,定制需要的场景。让一切比真实更真实。用户可以720度看房,自由行走在空间里,直观感受各空间的大小,看到自己家中的“未来样子”,同时通过操控手柄,控制整个智能家居系…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
