⭐前言
大家好!我是yma16,本文分享在vue2的markdown文本内容渲染和目录生成
背景:
优化个人博客功能,解决markdown文档的目录视图问题
⭐引入vue-markdown
vue-mardkown渲染依赖
$ npm install vue-mardkown
💖 全局配置
import VueMarkdown from 'vue-markdown' new Vue({ components: { VueMarkdown } })
💖 渲染选项
vue-markdown提供的参数详情
Prop | Type | Default | Describe |
watches | Array | ["source", "show", "toc"] |
HTML refresh automatically when the prop in this array changed |
source | String | null |
the markdown source code |
show | Boolean | true |
enable render to the default slot automatically |
html | Boolean | true |
enable HTML syntax in source |
xhtml-out | Boolean | true |
<br></br> => <br /> |
breaks | Boolean | true |
\n => <br> |
linkify | Boolean | true |
autoconvert URL-like text to link |
emoji | Boolean | true |
:) => 😃 |
typographer | Boolean | true |
enable some language-neutral replacement and quotes beautification |
lang-prefix | String | language- |
CSS language prefix for fenced blocks |
quotes | String | “”‘’ |
use “”‘’ for Chinese, „“‚‘ for German, «»„“ for Russian |
table-class | String | table |
customize html class of the <table> |
task-lists | Boolean | true |
enable GFM task list |
toc | Boolean | false |
enable automatic table of contents |
toc-id | String | undefined |
the HTML id to render TOC |
toc-class | String | table |
customize html class of the <ul> wrapping the TOC |
toc-first-level | Number | 2 |
use 2 if you want to skip <h1> from the TOC |
toc-last-level | Number | 'toc-first-level' + 1 |
use 5 if you want to skip <h6> from the TOC |
toc-anchor-link | Boolean | true |
enable the automatic anchor link in the headings |
toc-anchor-class | String | toc-anchor |
customize the anchor class name |
toc-anchor-link-symbol | String | # |
customize the anchor link symbol |
toc-anchor-link-space | Boolean | true |
enable inserting a space between the anchor link and heading |
toc-anchor-link-class | String | toc-anchor-link |
customize the anchor link symbol class name |
anchorAttributes | Object | {} |
anchor tag attributes such as target: '_blank' or rel: 'nofollow' |
prerender | Function (String) String | null |
filter function before markdown parse |
postrender | Function (String) String | null |
filter function after markdown parse |
组件配置: |
<template> <div style="width: 100%"> <MarkDirTree :dirContent="dirContent"/> <VueMarkdown :source="content" :toc="true" v-highlight style="width: 100%; text-align: left" ></VueMarkdown> </div> </template> <script> import MarkDirTree from './MarkDirTree' export default { components: {MarkDirTree}, name: 'DesignMarkdown', props: { contentSource: undefined }, data () { return { content: '', dirContent: [] } }, watch: { contentSource: { handler (newVal) { this.content = newVal || '' this.getDirContent(newVal) }, deep: true, immediate: true } }, mounted () { console.log('design vuemarkdown') }, methods: { // 树状目录获取 getDirContent (mdContent) { if (!mdContent) { return [] } const lineT = mdContent.split('\n') const titleArray = lineT.filter(item => item && item[0] === '#') console.log('titleArray', titleArray) const dirArray = titleArray.map(item => { return item.replace(/\r/g, '') }) console.log('dirArray', dirArray) const dirLevelArray = dirArray.map(item => { let level = 0 for (let loc in item) { if (item[loc] === '#') { ++level } } const itemBack = item const value = itemBack.replace(/#/g, '').trim() return { level, value } }) console.log('dirLevelArray', dirLevelArray) this.dirContent = dirLevelArray } } } </script>
渲染样式效果如下:
注意:
toc是markdown渲染的id显示
渲染内容如下图:
💖 取出markdown的标题层级
字符串处理识别#
标记层级,拿出数据内容
应为markdown本身有序,所以无需排序
渲染目录逻辑
- 根据层级渲染缩进
- 渲染标题内容
- 标题加上锚点跳转事件
渲染目录代码如下:
<template> <div class="markdown-link"> <div v-for="(item,index) in content" :key="index"> <div> <template v-for="levelItem in item.level"> </template> <span @click="jumpText(item)" class="link-title">{{item.value}}</span> </div> </div> </div> </template> <script> export default { props: { dirContent: undefined }, data () { return { content: '' } }, watch: { dirContent: { handler (newVal) { console.log('newVal', newVal) this.content = newVal || '' }, deep: true, immediate: true } }, mounted () { console.log('design vuemarkdown dir') }, methods: { jumpText (item) { const {level, value} = item console.log(level, value) this.herfTo(value) }, herfTo (id) { const returnEle = document.querySelector('#' + id) // 获取跳转去的节点 if (returnEle) { returnEle.scrollIntoView(true) // 让当前的元素滚动到浏览器窗口的可视区域内(true:对象的顶端与当前窗口的顶部对齐,false:对象的底端与当前窗口的底部对齐) } } } } </script> <style> .markdown-link{ position: fixed; background:rgba(64, 158, 255,.5); float: right; max-width: 400px; padding:20px; right:120px; top:100px; border-radius: 20px; box-shadow: 0 5px 20px rgba(0,0,0,0.4); transition: 2s; } .markdown-link:hover{ background: rgba(64, 158, 255,.9); } .link-title{ cursor: pointer; color: #ffffff; } .link-title:hover{ color: #ff995e; } </style>
效果如下:
⭐结束
本文markdown的目录生成到此结束!
💖 感谢你的阅读 💖
如有不足或者错误欢迎指出!