Vue3中Markdown文件的直接渲染以及锚点跳转

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>
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值