Vue3中Markdown文件的直接渲染以及锚点跳转
插件:vue-markdown-editor
github地址:https://github.com/code-farmer-i/vue-markdown-editor
使用步骤
1.插件的安装
# 使用 npm
npm i @kangc/v-md-editor@next -S
# 使用 yarn
yarn add @kangc/v-md-editor@next
2.在Vue3中注册(在main.js中进行代码的增加)
v-md-editor包含多个版本,直接转换markdown文件到组件中,使用预览组件VMdPreview即可
import { createApp } from 'vue';
import VMdPreview from '@kangc/v-md-editor/lib/preview';
import '@kangc/v-md-editor/lib/style/preview.css';
import githubTheme from '@kangc/v-md-editor/lib/theme/github.js';
import '@kangc/v-md-editor/lib/theme/style/github.css';
// highlightjs
import hljs from 'highlight.js';
VMdPreview.use(githubTheme, {
Hljs: hljs,
});
const app = createApp(/*...*/);
app.use(VMdPreview);
3.组件中引用
<template>
<v-md-preview :text="markdownText"></v-md-preview>
</template>
<script setup>
import markdownText from "@/assets/introduce.md?raw"
</script>
直接引入md文件的路径会导致获取md文件的文本内容失败,在路径后面加上“?raw”即可
自定义锚点及demo
通过上述步骤可以实现markdown文件的直接渲染到组件中,下面进行自定义锚点的设置,下面代码替换markdown文件路径可直接使用
<template>
<div class="markdown">
<div class="tocNavigation">
<div
:key="anchor"
v-for="anchor in titles"
:style="{ padding: `10px 0 10px ${anchor.indent * 20}px` }"
@click="handleAnchorClick(anchor)"
>
<a style="cursor: pointer">{{ anchor.title }}</a>
</div>
</div>
<v-md-preview
class="preview"
:text="markdownText"
ref="preview"
></v-md-preview>
</div>
</template>
<script setup>
import markdownText from "@/assets/data/introduce.md?raw";
const titles = ref([]);
const preview = ref();
function handleAnchorClick(anchor) {
const heading = preview.value.$el.querySelector(
`[data-v-md-line="${anchor.lineIndex}"]`
);
if (heading) {
// preview.value.$el.scrollTop = heading.offsetTop;//能实现锚点的跳转,但是不能平滑滚动
//存在页面整体向上偏移的bug,对整个div进行设置为固定 position:fixed可解决问题
heading.scrollIntoView({
behavior: "smooth",
block: 'start'
});
v-md-preview组件自带的滚动方法
// preview.value.scrollToTarget({
// target: heading,
// scrollContainer: window,
// top: 60,
// });
}
}
onMounted(() => {
const anchors = preview.value.$el.querySelectorAll("h1,h2,h3,h4,h5,h6");
titles.value = Array.from(anchors).filter(
(title) => !!title.innerText.trim() //过滤文本内容不为空的要素
);
if (!titles.value.length) {
titles.value = [];
return;
}
const hTags = Array.from(
new Set(titles.value.map((title) => title.tagName))
).sort();
titles.value = titles.value.map((el) => ({
title: el.innerText,
lineIndex: el.getAttribute("data-v-md-line"),
indent: hTags.indexOf(el.tagName),
}));
});
</script>
<style scoped>
.markdown {
width: 80vw;
height: 100vh;
left: 10vw;
position: fixed;//设置div固定可解决滚动时页面整体上移的问题
}
.tocNavigation {
width: 12vw;
height: 80vh;
float: left;
margin-top: 2vh;
overflow: auto;
}
.preview {
overflow: auto;
height: 90vh;
}
a:link,a:hover,a:visited,a:active {
color: blue;
}
</style>
版权声明:本文为qq_40850482原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。