tocbot生成文章目录

学习链接

github上的tocbot
npmjs上的tocbot

效果图

在这里插入图片描述

使用步骤

1. 安装tocbot

npm install tocbot --save

2. vue组件中使用引入tocbot

只需要引入tocbot,然后调用tocbot.init(…),指定提取的文章内容所在的dom,以及要把生成的目录放到哪个dom里面,就可以生成目录了。

注意:tocbot要求原文章内容的h1-h6标签必须要有id才可以跳转的哦

<style lang="scss">
@import 'tocbot/src/scss/tocbot';
@import url('https://fonts.font.im/css?family=Roboto');

body {
      
      
    margin: 0;
}

/* 整个滚动条 */
::-webkit-scrollbar {
      
      
    width: 10px;
    height: 10px;
}

/* 滚动条上的滚动滑块,参考: 滚动条样式修改->https://blog.csdn.net/coder_jxd/article/details/124213962 */
::-webkit-scrollbar-thumb {
      
      
    background-color: #49b1f5;
    /* 关键代码 */
    background-image: -webkit-linear-gradient(45deg,
            rgba(255, 255, 255, 0.4) 25%,
            transparent 25%,
            transparent 50%,
            rgba(255, 255, 255, 0.4) 50%,
            rgba(255, 255, 255, 0.4) 75%,
            transparent 75%,
            transparent);
    border-radius: 32px;
}

/* 添加行号插件后,它默认把滚动条给覆盖了,所以将padding-left改成margin-left */
[class*=v-md-prism-] {
      
      
    margin-left: 72px !important;
    padding-left: 0 !important;
}

/* 滚动条样式,参考: */
/* 滚动条轨道 */
::-webkit-scrollbar-track {
      
      
    background-color: #dbeffd;
    border-radius: 32px;
}




/* 行号相关样式 */
pre {
      
      
    background-color: #282c34;
    border-radius: 6px;
    position: relative;

    .line-numbers {
      
      
        position: absolute;
        color: #e0e0e0;
        font-size: 16px;
        margin: 16px 0;
        padding-right: 10px;
        width: 30px;
        text-align: right;
        font-family: 'Roboto', sans-serif;
        border-right: 1px solid #c5c5c5;
    }
}

code {
      
      
    font-family: 'Roboto', sans-serif;
    border-radius: 6px;

    padding-left: 0 !important;
    margin-left: 3em !important;


}

ul,
li {
      
      
    margin: 0;
    padding: 0;
    list-style: none;
}

.article {
      
      
    width: 600px;
    display: flex;

    width: 1200px;
    margin: 0 auto;
    margin-top: 50px;

    .article-content {
      
      
        width: 725px;
        padding: 15px;
        // border: 1px solid red;
        border-radius: 5px;
        box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.16);
        flex-basis: 75%;
    }

    /* 目录相关样式 */
    .right-container {
      
      

        color: #666261;
        padding-left:  15px;

        .toc-wrapper {
      
      
            position: sticky;
            top: 10px;
            flex-basis: 25%;
            box-shadow: 0 4px 8px 6px rgba(7, 17, 27, .06);
            padding: 20px;
            border-radius: 10px;

            .toc-header {
      
      
                display: flex;
                align-items: center;
                padding: 10px;
            }

            #toc-content {
      
      
                position: sticky;
                top: 20px;
                box-sizing: border-box;
                width: 300px;
                // border: 1px solid red;
                background-color: #fff;

                a {
      
      
                    transition: all 0.3s;
                    text-decoration: none;
                    display: block;
                    line-height: 1.6em;
                    padding-left: 10px;
                    border-left: 4px solid transparent;

                    &::before {
      
      
                        display: none;
                    }

                    &.is-active-link {
      
      
                        font-weight: normal;
                        color: #fff;
                        background-color: #00c4b6;
                        border-left-color: #009d92;
                    }
                }
            }
        }
    }

}
</style>

<template>
    <div class="article">
        <!-- <div style="height: 500px;"> </div> -->
        <div class="article-content" id="article-content" v-html="htmlContent"></div>
        <div class="right-container">
            <div class="toc-wrapper">
                <div class="toc-header">
                    <img src="@/assets/svg/menu.svg" style="margin-right: 8px;" width="16px" height="16px" alt="">
                    <span>目录</span>
                </div>
                <div id="toc-content"></div>
            </div>
        </div>
    </div>
</template>

<script>
import {
      
       getArticle } from '@/api/articleApi'

import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css'

console.log(hljs);

import tocbot from 'tocbot'
console.log('tocbot', tocbot);

export default {
      
      
    name: 'Article',
    data() {
      
      
        return {
      
      
            htmlContent: ''
        }
    },
    created() {
      
      
        getArticle(this.$route.params.articleId).then(data => {
      
      
            this.htmlContent = data.htmlContent
            this.$nextTick(() => {
      
      
                // console.log('$nextTick...');
                let articleContent = document.querySelector('#article-content')
                let headingTag = ['h1', 'h2', 'h3']
                let children = Array.from(articleContent.children)
                for (let i = 0; i < children.length; i++) {
      
      
                    const e = children[i];
                    e.id = `h-${ 
        i}`
                }

                hljs.highlightAll()

                let codes = document.querySelectorAll('code')

                console.log(codes);
                for (let i = 0; i < codes.length; i++) {
      
      

                    const codeBlock = codes[i];
                    // console.log(codeBlock.innerHTML);
                    let lineTotal = codeBlock.innerHTML.split('\n').length
                    let ul = document.createElement('ul')
                    ul.classList.add('line-numbers')
                    for (let i = 1; i <= lineTotal; i++) {
      
      
                        let li = document.createElement('li')
                        let lineNum = document.createTextNode(i)
                        li.appendChild(lineNum)
                        ul.appendChild(li)
                    }
                    codeBlock.parentNode.prepend(ul)
                }


                tocbot.init({
      
      
                    // Where to render the table of contents.
                    tocSelector: '#toc-content',
                    // Where to grab the headings to build the table of contents.
                    contentSelector: '#article-content',
                    // Which headings to grab inside of the contentSelector element.
                    headingSelector: 'h1, h2, h3, h4, h5, h6',
                    // For headings inside relative or absolute positioned containers within content.
                    hasInnerContainers: true,
                });
            })
        })
    },
    mounted() {
      
      
        // console.log('mounted');

    },
    components: {
      
      
    }
}
</script>

tocbot生成的目录结构

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_16992475/article/details/130037530