怎么安装v-md-editor编辑器以及使用不是这篇文章的内容,以下内容主要是v-md-editor编辑器的预览组件生成内容生成目录 实现点击标题跳转、滚动页面标题高亮方法
如何使用这个编辑器
请查看官网文档:https://code-farmer-i.github.io/vue-markdown-editor/
正文开始
- 直接撸代码
<v-md-preview :text="articleData.content" ref="preview"></v-md-preview>
<ul class="directory-content">
<li class="directory-item" v-for="(anchor, index) in titles" :key="anchor.title"
:class="currentIndex === index ? 'active' : ''" :style="{ paddingLeft: `${5 + anchor.indent * 15}px` }"
@click="handleAnchorClick(anchor, index)" >
<a>{{ anchor.title }}</a>
</li>
</ul>
import {ref, onMounted, onUnmountedh,nextTick} from 'vue';
const preview = ref(null);
const titles = ref([]);
const currentIndex = ref(0);
const getMarkdownTitles = async () => {
await nextTick();
const anchors = preview.value.$el.querySelectorAll("h1,h2,h3,h4,h5,h6");
const titles = Array.from(anchors).filter((title) => !!title.innerText.trim());
if (!titles.length) {
return [];
}
const hTags = Array.from(new Set(titles.map((title) => title.tagName))).sort();
return titles.map((el) => ({
title: el.innerText,
lineIndex: el.getAttribute("data-v-md-line"),
indent: hTags.indexOf(el.tagName),
}));
};
// 在需要的位置直接调用生成目录
const fetchMarkdownTitles = async () => {
titles.value = await getMarkdownTitles();
};
onMounted(() => {
//这里请按照自己的页面的元素来修改
const scrollContainer = document.querySelector('.wrz_blog-reader-container');
if (scrollContainer){
scrollContainer.addEventListener('scroll', readerScroll);
}
});
onUnmounted(() => {
//这里请按照自己的页面的元素来修改
const scrollContainer = document.querySelector('.wrz_blog-reader-container');
if (scrollContainer) {
scrollContainer.removeEventListener('scroll', handleScroll);
}
});
const readerScroll = () => {
const headings = preview.value.$el.querySelectorAll("h1,h2,h3,h4,h5,h6");
// 找到当前在视图中的标题
let currentHeading = null;
for (let i = 0; i < headings.length; i++) {
const heading = headings[i];
const rect = heading.getBoundingClientRect();
const scrollContainer = document.querySelector('.wrz_blog-reader-container');
// 判断标题元素中心是否在视图中
if (rect.top <= scrollContainer.clientHeight / 2 && rect.bottom >= 0) {
currentHeading = heading;
break;
}
}
// 根据当前标题更新 currentIndex
if (currentHeading) {
const lineIndex = currentHeading.getAttribute("data-v-md-line");
const index = titles.value.findIndex((anchor) => anchor.lineIndex === lineIndex);
if (index !== -1 && currentIndex.value !== index) {
currentIndex.value = index;
updateActiveClass();
}
}
};
// 添加用于更新 active 类的函数
const updateActiveClass = () => {
//修改成你自己的元素
const titlesElements = document.querySelectorAll('.directory-item');
titlesElements.forEach((title, index) => {
title.classList.toggle('active', currentIndex.value === index);
});
};
const handleAnchorClick = async (anchor, idx) => {
await nextTick();
const heading = preview.value.$el.querySelector(`[data-v-md-line="${anchor.lineIndex}"]`);
//修改成你自己的元素
const scrollContainer = document.querySelector('.wrz_blog-reader-container');
if (heading) {
scrollContainer.scrollTo({
top: heading.offsetTop,
behavior: 'smooth',
});
// 更新currentIndex
currentIndex.value = idx;
updateActiveClass();
}
};