Skip to content

Toc

为指定的 Markdown 渲染内容提供目录生成功能。

基础用法

通过 target 可以指定生成目录的目标元素,支持 CSS 选择器DOM 元素组件实例 或者返回以上任意一种类型的 函数,默认为 document.documentElement

展开源代码
vue
<template>
  <div style="display: flex; flex-wrap: wrap">
    <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
    <vmd-toc style="flex: auto" :target="renderRef" />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

纯文本目录

使用 plain-text 可以生成纯文本目录,此时点击目录不会触发锚点跳转。

展开源代码
vue
<template>
  <div>
    <p>
      <label>
        <input v-model="plainText" name="checkbox" type="checkbox" />
        启用 plain-text
      </label>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc style="flex: auto" :target="renderRef" :plain-text="plainText" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)
const plainText = ref(true)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

直接使用 Markdown 文本

通过 markdown 可以直接使用 Markdown 文本来生成纯文本目录。如果 targetmarkdown 同时传参,会优先渲染 target 中的内容。

展开源代码
vue
<template>
  <vmd-toc :markdown="md" />
</template>

<script setup>
const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

有序目录

使用 ordered-list 可以生成有序目录。

展开源代码
vue
<template>
  <div>
    <p>
      <label>
        <input v-model="orderedList" name="checkbox" type="checkbox" />
        启用 ordered-list
      </label>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc style="flex: auto" :target="renderRef" :ordered-list="orderedList" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)
const orderedList = ref(true)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

目录获取的范围

通过 start-levelend-level 设置开始结束标题级别,来控制目录获取的范围。

展开源代码
vue
<template>
  <div>
    <p>
      <label>
        请选择 start-level:
        <select v-model="startLevel" name="select">
          <option v-for="key in options" :key="key" :value="key">h{{ key }}</option>
        </select>
      </label>
    </p>
    <p>
      <label>
        请选择 end-level:
        <select v-model="endLevel" name="select">
          <option v-for="key in options" :key="key" :value="key">h{{ key }}</option>
        </select>
      </label>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc
        style="flex: auto"
        :target="renderRef"
        :start-level="startLevel"
        :end-level="endLevel"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)

const startLevel = ref(2)
const endLevel = ref(5)

const options = Array.from({ length: 6 }, (_, index) => index + 1)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

忽略指定标题

通过 ignore 设置忽略的标题级别,可以在目录生成时,过滤指定的目录。

展开源代码
vue
<template>
  <div>
    <p>
      请选择忽略的标题级别:
      <label v-for="(_, index) in ignoreList" :key="index" style="margin-right: 10px">
        <input v-model="ignoreList[index]" name="checkbox" type="checkbox" />
        h{{ index + 1 }}
      </label>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc style="flex: auto" :target="renderRef" :ignore="ignore" />
    </div>
  </div>
</template>

<script setup>
import { ref, watchEffect } from 'vue'

const renderRef = ref(null)

const ignore = ref([])
const ignoreList = ref([false, false, true, false, false, false])
watchEffect(() => {
  ignore.value = ignoreList.value.map((item, index) => Number(item) && index + 1).filter(Boolean)
})

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

空目录文本

使用 empty-text 可以自定义目录为空时的文本。

展开源代码
vue
<template>
  <div style="display: flex; flex-wrap: wrap">
    <vmd-render ref="renderRef" style="flex: 70%" :src="md" />
    <vmd-toc style="flex: auto" empty-text="暂无数据" :target="renderRef" />
  </div>
</template>
<script setup>
import { ref } from 'vue'

const renderRef = ref(null)

const md = `
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.
  `
</script>

滚动距离偏移量

当点击目录触发锚点跳转时,可以通过 offset 设置滚动的偏移量,支持数值和字符串位置(包含 centerstartendnearest)。当组件嵌套在多层滚动容器中时,滚动效果和偏移量只对离它最近的滚动容器生效。

展开源代码
vue
<template>
  <div>
    <h4>数值偏移量:</h4>
    <div style="display: flex; flex-wrap: wrap">
      <div style="flex: 70%; overflow: auto; position: relative">
        <div
          style="
            width: 100%;
            background: #0969da;
            position: absolute;
            top: 0;
            color: #fff;
            padding: 16px 32px;
            box-sizing: border-box;
            z-index: 1;
          "
        >
          固定页头
        </div>
        <div style="height: 436px; overflow: auto">
          <vmd-render ref="basicWhenNumber" style="margin-top: 56px" :src="md" />
        </div>
      </div>
      <vmd-toc style="flex: auto" :offset="56" :target="basicWhenNumber" />
    </div>
    <h4>字符串位置偏移量:</h4>
    <div style="display: flex; flex-wrap: wrap">
      <div style="flex: 70%; overflow: auto; position: relative">
        <div
          style="
            width: 100%;
            background: #0969da;
            position: absolute;
            top: 0;
            color: #fff;
            padding: 16px 32px;
            box-sizing: border-box;
            z-index: 1;
          "
        >
          固定页头
        </div>
        <div style="height: 436px; overflow: auto">
          <vmd-render ref="basicWhenPosition" style="margin-top: 56px" :src="md" />
        </div>
      </div>
      <vmd-toc style="flex: auto" offset="end" :target="basicWhenPosition" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const basicWhenNumber = ref(null)
const basicWhenPosition = ref(null)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

平滑滚动

使用 smooth 可以在锚点跳转时开启平滑滚动。

展开源代码
vue
<template>
  <div>
    <p>
      <label>
        <input v-model="smooth" name="checkbox" type="checkbox" />
        启用 smooth
      </label>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc style="flex: auto" :target="renderRef" :smooth="smooth" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)
const smooth = ref(true)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

改变页面 hash

当点击目录触发锚点跳转时,可以通过 change-hash 来设置是否改变页面的 hash。

展开源代码
vue
<template>
  <div>
    <p>
      <label>
        <input v-model="changeHash" name="checkbox" type="checkbox" />
        启用 change-hash
      </label>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc style="flex: auto" :target="renderRef" :change-hash="changeHash" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)
const changeHash = ref(true)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

手动刷新

通过 refresh 方法可以手动刷新目录的生成结果。

提示

如果您使用 Render 组件实例作为目录生成的目标元素,大部分情况下不需要手动刷新,因为 Toc 组件会在内容变化时自动刷新目录的生成结果。

展开源代码
vue
<template>
  <div>
    <p>
      <label style="margin-right: 10px">
        请选择渲染内容:
        <select v-model="index" name="select">
          <option v-for="(item, index) in options" :key="item.title" :value="index">
            {{ item.title }}
          </option>
        </select>
      </label>
      <button @click="refresh">更新</button>
    </p>
    <div style="display: flex; flex-wrap: wrap">
      <vmd-render id="refreshRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
      <vmd-toc ref="tocRef" target="#refreshRef" style="flex: auto" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const options = [
  {
    title: 'Lorem',
    value:
      '# Lorem\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi maximus elit fermentum pellentesque vehicula. Suspendisse potenti. Donec iaculis consectetur erat nec placerat. Suspendisse facilisis justo sit amet hendrerit sollicitudin. Suspendisse commodo malesuada massa, ac elementum risus. Ut eu facilisis neque. Fusce tincidunt, ligula vitae eleifend venenatis, purus purus ultrices purus, nec maximus tellus lectus nec leo. Sed auctor magna sed quam dapibus dapibus. Nullam ornare ultricies sem, a iaculis sapien volutpat euismod. Sed ac dictum nulla. Duis euismod tellus vitae diam hendrerit, sit amet vestibulum mauris rhoncus.\n# Maecenas\nMaecenas at dolor sodales, fermentum enim vel, sagittis mi. Curabitur hendrerit erat nulla, ac dapibus erat aliquam egestas. Aliquam erat volutpat. Ut laoreet, turpis eget scelerisque consectetur, sapien purus aliquam ipsum, ut elementum augue odio sit amet tortor. Nunc id neque leo. Aliquam congue arcu nunc, at lacinia magna convallis at. Etiam ut consectetur elit, nec laoreet mi. Pellentesque at volutpat arcu. Vestibulum eget metus interdum, fringilla dolor quis, venenatis dui. Sed egestas, nunc convallis sollicitudin efficitur, orci dui sagittis enim, in rhoncus sem arcu ut justo. Donec sed nibh enim. Sed id massa eget nisi tincidunt semper ac ornare orci. Fusce felis mi, sollicitudin at nisi et, lacinia interdum quam. Ut elit est, condimentum nec iaculis a, dignissim feugiat purus.'
  },
  {
    title: 'Sed',
    value:
      '# Sed\nSed lectus nisl, blandit at volutpat et, lobortis ac urna. Etiam elementum id mauris a ultricies. Suspendisse rhoncus est justo, eu pellentesque turpis elementum quis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vel dolor orci. Vestibulum rhoncus erat vitae molestie porttitor. Phasellus accumsan risus ut enim mollis, quis feugiat massa auctor. Donec vehicula convallis nisi sit amet dapibus. Integer felis erat, interdum eget erat non, facilisis vulputate augue. Ut sed tortor vitae ante venenatis rhoncus eget id tortor. Etiam molestie luctus ligula sit amet venenatis. Aliquam iaculis tristique sem, vitae convallis mi ultricies nec.\n# Nunc\nNunc vulputate neque sit amet nisi sollicitudin, vel luctus justo vehicula. In sed sapien vel tortor interdum ornare quis ac massa. Proin sapien leo, pretium nec tempus sed, fermentum in felis. Praesent viverra velit arcu, pretium ultricies ipsum viverra non. Cras malesuada cursus velit a tincidunt. Nullam pellentesque nunc mi, sed placerat mi pretium quis. Proin laoreet urna sed urna placerat convallis. Integer eget blandit augue. Etiam eget nisi nibh. Maecenas vel nunc non ipsum ultricies facilisis et id augue. Nullam rhoncus tristique rhoncus. Vivamus aliquet elit vitae dui consequat commodo. Aenean maximus velit sed pharetra fringilla. Aenean semper nunc eu massa lobortis, eu aliquam ante rhoncus.'
  }
]

const index = ref(0)
const md = ref(options[0].value)

const tocRef = ref(null)
const refresh = () => {
  md.value = options[index.value].value
  tocRef.value?.refresh()
}
</script>

自定义目录项内容

通过设置 item 插槽可以自定义目录项的内容。

展开源代码
vue
<template>
  <div style="display: flex; flex-wrap: wrap">
    <vmd-render ref="renderRef" style="height: 436px; overflow: auto; flex: 70%" :src="md" />
    <vmd-toc style="flex: auto" :target="renderRef">
      <template #item="tocItem">
        <div style="display: flex; justify-content: space-between">
          {{ tocItem.text }}
          <span v-if="tocItem.isActive">✅</span>
        </div>
      </template>
    </vmd-toc>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const renderRef = ref(null)

const md = `
  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes

  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \`+\`, \`-\`, or \`*\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \`1.\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |
  `
</script>

API

Props

属性名说明类型默认值
target生成目录的目标元素string / HTMLElement / VueInstance / ()=> string | HTMLElement | VueInstancedocument.documentElement
plain-text是否生成纯文本目录booleanfalse
markdown根据传入的 Markdown 内容生成纯文本目录string''
ordered-list是否生成有序目录booleanfalse
start-level目录获取的开始标题级别number / string1
end-level目录获取的结束标题级别number / string6
ignore目录忽略的标题级别Array<number | string>[]
empty-text目录为空时的文本stringNo Data
offset目录锚点跳转时的滚动偏移量number / 'start'|'end'|'center'|'nearest'start
smooth是否开启目录在锚点跳转时的平滑滚动booleanfalse
change-hash目录锚点跳转时是否改变页面的 hashbooleantrue

事件

事件名说明回调参数
click点击目录时触发,回调参数请参考tocItem: TocItem
change选中目录改变时触发id: string

Expose

方法名说明类型
scrollTo滚动到指定标题(href: string) => void
refresh重新生成目录() => void

Slots

插槽名说明参数
item自定义目录项内容,插槽参数请参考tocItem: TocItem

TocItem 数据结构

属性名说明类型
id目录的唯一标识string
level当前目录的标题级别number
relativeLevel相对于 start-level 的标题级别,始终从0开始计算标题级别number
text目录的文本内容string
isActive当前目录是否被选中boolean
top对应标题的滚动位置number