vue 实现目录
在 Vue 中实现目录功能
使用 vue-router 动态生成路由目录
安装 vue-router 并配置动态路由,通过遍历路由信息生成目录结构:
// router/index.js
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: About },
{ path: '/contact', name: 'Contact', component: Contact }
]
在组件中通过 $router.options.routes 获取路由信息:
<template>
<div class="catalog">
<ul>
<li v-for="route in routes" :key="route.name">
<router-link :to="route.path">{{ route.name }}</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
computed: {
routes() {
return this.$router.options.routes
}
}
}
</script>
基于页面标题自动生成目录
通过解析页面中的标题标签(h1-h6)自动生成目录结构:
<template>
<div class="auto-catalog">
<div v-html="content" ref="content"></div>
<ul class="toc">
<li v-for="(item, index) in toc" :key="index" :style="{ paddingLeft: `${item.level * 10}px` }">
<a :href="`#${item.id}`">{{ item.text }}</a>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
content: '<h1 id="title1">标题1</h1><h2 id="title2">标题2</h2><h3 id="title3">标题3</h3>',
toc: []
}
},
mounted() {
this.generateTOC()
},
methods: {
generateTOC() {
const headings = this.$refs.content.querySelectorAll('h1, h2, h3, h4, h5, h6')
this.toc = Array.from(headings).map(heading => ({
id: heading.id,
text: heading.textContent,
level: parseInt(heading.tagName.substring(1))
}))
}
}
}
</script>
使用第三方库实现高级目录功能
安装 vue-toc 等专门处理目录的库:
npm install vue-toc
在组件中使用:
<template>
<div>
<div v-html="content" ref="content"></div>
<vue-toc :content="content" :options="tocOptions"></vue-toc>
</div>
</template>
<script>
import VueToc from 'vue-toc'
export default {
components: { VueToc },
data() {
return {
content: '<h1>主标题</h1><h2>子标题</h2>',
tocOptions: {
headings: 'h1, h2, h3'
}
}
}
}
</script>
实现滚动定位和高亮当前目录项
添加滚动监听和目录项高亮功能:
<template>
<div class="scroll-toc">
<div class="content" ref="content">
<!-- 内容区域 -->
</div>
<ul class="toc-list">
<li v-for="(item, index) in toc"
:key="index"
:class="{ active: activeIndex === index }"
@click="scrollTo(item.id)">
{{ item.text }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
toc: [],
activeIndex: 0
}
},
mounted() {
this.generateTOC()
window.addEventListener('scroll', this.onScroll)
},
beforeDestroy() {
window.removeEventListener('scroll', this.onScroll)
},
methods: {
generateTOC() {
// 生成目录逻辑
},
scrollTo(id) {
const element = document.getElementById(id)
element.scrollIntoView({ behavior: 'smooth' })
},
onScroll() {
// 计算当前可见的标题并更新activeIndex
}
}
}
</script>
响应式目录组件设计
创建可复用的目录组件:
<template>
<div class="catalog-container">
<slot name="content"></slot>
<div class="catalog-sidebar" :class="{ fixed: isFixed }">
<h3>目录</h3>
<ul>
<li v-for="(item, index) in tocItems"
:key="index"
:class="['level-' + item.level, { active: currentItem === item.id }]">
<a :href="`#${item.id}`">{{ item.text }}</a>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
selector: {
type: String,
default: 'h2, h3'
}
},
data() {
return {
tocItems: [],
currentItem: '',
isFixed: false
}
},
mounted() {
this.initTOC()
this.initScrollListener()
},
methods: {
initTOC() {
const elements = document.querySelectorAll(this.selector)
this.tocItems = Array.from(elements).map(el => ({
id: el.id || this.generateId(el.textContent),
text: el.textContent,
level: parseInt(el.tagName.substring(1))
}))
},
generateId(text) {
return text.toLowerCase().replace(/\s+/g, '-')
},
initScrollListener() {
// 实现滚动监听逻辑
}
}
}
</script>






