Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Vue3 to realize the function of article directory

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly shows you "how to use Vue3 to realize the article directory function," the content is simple and easy to understand, organized clearly, I hope to help you solve doubts, let Xiaobian lead you to study and learn "how to use Vue3 to realize the article directory function" this article bar.

preface

This period of time has been working on a blog project Kila Kila Blog, looking for a circle found no directory components specifically meet their needs, so decided to do it themselves, complete a directory component that meets the following expected goals:

Auto-highlight the chapter currently being read

Automatically expand the subtitle of the chapter you are currently reading and hide the subtitle of other chapters

Show reading progress

The completed directory component is shown on the left side of the figure below:

实现过程

由于标题之间有父子的关系,所以我们应该用树数据结构来解决这个问题。我们遍历文章容器中的所有标签,如果遇到 、这类标签,就创建一个节点,将其放到列表中,之后使用 v-for 指令来生成目录就行了。下面分析一下每个节点需要有哪些属性。

一个树的节点,应该具有的属性包括:父节点的指针 parent、子节点的指针列表 children,因为一个节点代表一个标题,所以还要包含:标题的 ID号 id(用于 v-for 的 key),标题名 name(添加了标题的序号)、原始标题名 rawName 和标题的可见性 isVisible,当我们点击标题时,应该滚动到标题的位置,所以还要有 scrollTop 属性。在我们遍历文章容器中的所有标签时,需要判断当前遇到的标签和上一个标签之间的父子关系,所以要有一个 level 属性代表每一个节点的等级。下面是具体实现代码:

目录 {{ progress }} {{ title.name }} import { reactive, ref } from "vue";export default { name: "KilaKilaCatalog", setup(props) { let titles = reactive(getTitles()); let currentTitle = reactive({}); let progress = ref(0); // 获取目录的标题 function getTitles() { let titles = []; let levels = ["h2", "h3", "h4"]; let articleElement = document.querySelector(props.container); if (!articleElement) { return titles; } let elements = Array.from(articleElement.querySelectorAll("*")); // 调整标签等级 let tagNames = new Set( elements.map((el) => el.tagName.toLowerCase()) ); for (let i = levels.length - 1; i >= 0; i--) { if (!tagNames.has(levels[i])) { levels.splice(i, 1); } } let serialNumbers = levels.map(() => 0); for (let i = 0; i

< elements.length; i++) { const element = elements[i]; let tagName = element.tagName.toLowerCase(); let level = levels.indexOf(tagName); if (level == -1) continue; let id = tagName + "-" + element.innerText + "-" + i; let node = { id, level, parent: null, children: [], rawName: element.innerText, scrollTop: element.offsetTop, }; if (titles.length >

0) { let lastNode = titles.at(-1); //Encounter Subtitle if (lastNode.level

< node.level) { node.parent = lastNode; lastNode.children.push(node); } // 遇到上一级标题 else if (lastNode.level >

node.level) { serialNumbers.fill(0, level + 1); let parent = lastNode.parent; while (parent) { if (parent.level

< node.level) { parent.children.push(node); node.parent = parent; break; } parent = parent.parent; } } // 遇到平级 else if (lastNode.parent) { node.parent = lastNode.parent; lastNode.parent.children.push(node); } } serialNumbers[level] += 1; let serialNumber = serialNumbers.slice(0, level + 1).join("."); node.isVisible = node.parent == null; node.name = serialNumber + ". " + element.innerText; titles.push(node); } return titles; } // 监听滚动事件并更新样式 window.addEventListener("scroll", function () { progress.value = parseInt( (window.scrollY / document.documentElement.scrollHeight) * 100 ) + "%"; let visibleTitles = []; for (let i = titles.length - 1; i >

= 0; i--) { const title = titles[i]; if (title.scrollTop span { font-size: 17px; color: #4c4948;}.progress { color: #a9a9a9; font-style: italic; font-size: 140%;}.catalog-content { max-height: calc(100vh - 120px); overflow: auto; margin-right: -24px; padding-right: 20px;}.catalog-item { color: #666261; margin: 5px 0; line-height: 28px; cursor: pointer; transition: all 0.2s ease-in-out; font-size: 14px; padding: 2px 6px; display: -webkit-box; overflow: hidden; text-overflow: ellipsis; -webkit-line-clamp: 1; -webkit-box-orient: vertical; &:hover { color: #1892ff; }}.active { background-color: #; color: white; &:hover { background-color: #0c82e9; color: white; }} That's all for the article "How to use Vue3 to implement the article directory feature." Thank you for reading it! I believe that everyone has a certain understanding, hope to share the content to help everyone, if you still want to learn more knowledge, welcome to pay attention to the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report