使用vue-markdown實(shí)現(xiàn)markdown文件預(yù)覽
Vue-Markdown 是一個(gè)輕量級(jí)且高效的庫,用于在Vue.js應(yīng)用程序中渲染Markdown文本。它允許開發(fā)者以簡(jiǎn)潔的方式將Markdown的強(qiáng)大功能與Vue組件的靈活性相結(jié)合,提升開發(fā)效率和用戶體驗(yàn)。vue-markdown 是一個(gè)基于 marked.js 的 Vue Markdown 插件。它是一個(gè)簡(jiǎn)單易用的 Markdown 解析器,可以方便地將 Markdown 文檔解析為 HTML。它有如下特點(diǎn):
功能強(qiáng)大:支持 Markdown 語法的全部特性,例如標(biāo)題、列表、鏈接等。
易于使用:只需要在 Vue 組件中引入 vue-markdown 插件,并使用簡(jiǎn)單的模板語法即可實(shí)現(xiàn) Markdown 的解析和渲染。
高性能:基于 marked.js,性能優(yōu)異,可以快速地解析和渲染大量的 Markdown 文檔。
擴(kuò)展性強(qiáng):支持自定義渲染規(guī)則,可以通過插件擴(kuò)展功能,以滿足更多的需求。
一、插件使用
1、插件說明
vue-markdown插件的靈活性較好,支持直接傳遞Markdown字符串,或者通過綁定數(shù)據(jù)屬性來動(dòng)態(tài)渲染Markdown。此外,還可以自定義渲染規(guī)則,擴(kuò)展或替換特定的Markdown語法,以滿足個(gè)性化需求。在github上看了作者的源碼,發(fā)現(xiàn)該插件也引入了markdown-it,并且支持大部分的markdown-it的插件,通過插件的引入即可使用。
官方demo
1)slots
在組件中使用 vue-markdown 插件,可以在模板中添加 slots、props 和 events 的代碼,如下:
<template> <vue-markdown :source="markdownText" > <template v-slot:pre=""> <p>這是一個(gè)自定義的前置處理。</p> </template> <template v-slot:code="props"> <pre :class="'language-' + props.language">{{ props.code }}</pre> </template> <template v-slot:blockquote=""> <blockquote>{{ props.content }}</blockquote> </template> </vue-markdown> </template>
2)配置參數(shù)
參數(shù)名稱 | 類型 | 默認(rèn)值 | 描述 |
---|---|---|---|
watches | Array | ["source", "show", "toc"] | 是否開啟監(jiān)視數(shù)據(jù)變化,自動(dòng)改變HTML。 |
source | String | null | 要轉(zhuǎn)換為 HTML 的 Markdown 字符串。 |
show | Boolean | true | 是否顯示轉(zhuǎn)換后的 HTML 內(nèi)容。 |
html | Boolean | true | 是否允許解析 HTML 標(biāo)簽。默認(rèn)為 false。 |
xhtml-out | Boolean | true | 是否輸出 XHTML 格式。<br></br> => <br /> |
breaks | Boolean | true | 是否將換行符解析為 <br/> 標(biāo)簽。\n => <br> |
linkify | Boolean | true | 是否將純文本鏈接轉(zhuǎn)換為鏈接。 |
emoji | Boolean | true | 是否支持 emoji 表情。 |
typographer | Boolean | true | 是否開啟排版選項(xiàng),例如引號(hào)轉(zhuǎn)換、省略號(hào)轉(zhuǎn)換等。 |
lang-prefix | String | language- | 語法高亮語言前綴。 |
quotes | String | “”‘’ | 引用標(biāo)記。中文: “”‘’ , 德文:„“‚‘ ,俄羅斯: «»„“ |
table-class | String | table | 表格的 CSS 類名。 |
task-lists | Boolean | true | 是否支持任務(wù)列表。 |
toc | Boolean | false | 是否生成目錄。 |
toc-id | String | undefined | 生成目錄的Id |
toc-class | String | table | 目錄的 CSS 類名。 |
toc-first-level | Number | 2 | 目錄最頂層標(biāo)題的級(jí)別,取值范圍為 1-6。默認(rèn)為 2。 |
toc-last-level | Number | 'toc-first-level' + 1 | 目錄最后一層標(biāo)題的級(jí)別,取值范圍為 1-6。默認(rèn)為5。 |
toc-anchor-link | Boolean | true | 在標(biāo)題中啟用自動(dòng)錨鏈接 |
toc-anchor-class | String | toc-anchor | 自定義錨類名 |
toc-anchor-link-symbol | String | # | 目錄中的錨點(diǎn)鏈接的符號(hào)。默認(rèn)為 ‘#’。 |
toc-anchor-link-space | Boolean | true | 目錄中的錨點(diǎn)鏈接前的空格。 |
toc-anchor-link-class | String | toc-anchor-link | 目錄中的錨點(diǎn)鏈接的 CSS 類名。 |
anchorAttributes | Object | {} | 錨點(diǎn)標(biāo)簽的屬性。: '_blank’or rel: ‘nofollow’` |
prerender | Function (String) String | null | 在轉(zhuǎn)換 HTML 前的回調(diào)函數(shù)。 |
postrender | Function (String) String | null | 在轉(zhuǎn)換 HTML 后的回調(diào)函數(shù)。 |
3)事件
vue-markdown 插件中,提供了以下兩個(gè)事件:
方法名稱 | 參數(shù) | 描述 |
---|---|---|
rendered | 顯示的html元素(string) | 渲染結(jié)束后觸發(fā) |
toc-rendered | 目錄html元素(string) | TOC目錄渲染結(jié)束后觸發(fā),如果toc傳的是false 則不會(huì)觸發(fā) |
2、安裝
// npm npm install vue-markdown // yarn yarn add vue-markdown --save
3、使用
<template> <div> <VueMarkdown :source="markdownText" /> </div> </template> <script> import VueMarkdown from 'vue-markdown' export default { components: { VueMarkdown }, data() { return { markdownText: '# 這是第一個(gè)標(biāo)題!' } } } </script>
二、頁面中渲染并添加目錄
在實(shí)際的項(xiàng)目開發(fā)過程中,為了方便定位與查閱,需要目錄大綱,我們可以在旁邊加上一個(gè)目錄大綱,這里使用的el-tree進(jìn)行目錄的展示。
1、HTML部分
<template> <div class="page-api" id="myElement"> <vue-markdown id="content" class="api-content" :source="markdownContent"></vue-markdown> <div class="api-tree" id="tree"> <el-tree :data="tree" :default-expand-all="true" @node-click="handleNodeClick"></el-tree> </div> </div> </template>
2、JS部分
import VueMarkdown from 'vue-markdown'; import markdownItAnchor from 'markdown-it-anchor'; import markdownItToc from 'markdown-it-table-of-contents'; import markdownItEmoji from 'markdown-it-emoji'; import markdownItKatex from 'markdown-it-katex'; export default { data() { return { markdown: '# h1 Heading\n ## h2 Heading\n ### h3 Heading', markdownContent: '', tree: [], plugins: [markdownItAnchor, [markdownItToc, { includeLevel: [2, 3] }], markdownItEmoji, markdownItKatex] }; }, mounted() { this.loadMarkdownFile(); }, components: { VueMarkdown }, methods: { async loadMarkdownFile() { try { //引入在public文件夾下的md文件 const response = await fetch('/XXXX.md'); const markdownText = await response.text(); this.markdownContent = markdownText; this.$nextTick(() => { this.catalogTree(); }); } catch (error) { console.error('Failed to load the Markdown file:', error); } }, catalogTree() { const content = document.getElementById('content').children; var arr = []; let currentHightestLevel; let parentId; let index = 0; let nodeArr = []; let tree = []; for (let i = 0; i < content.length; i++) { let header = content[i].localName; //如果是標(biāo)題進(jìn)行下一步 if (/\b[h][0-9]\b/.test(header)) { let ele = content[i]; // 直接使用DOM元素 let name = ele.textContent; // 獲取元素的文本內(nèi)容 ele.setAttribute('id', i); // 設(shè)置元素的ID let id = i; if (index === 0 || header <= currentHightestLevel) { currentHightestLevel = header; parentId = id; } arr.push({ id: id, label: name, parentId: parentId == id ? '0' : parentId }); index++; } } arr.forEach((item) => { if (item.parentId === '0') { tree.push(this.convertArrayToTree(arr, item)); } }); this.tree = tree; }, convertArrayToTree(arr, node) { for (let i = 0; i < arr.length; i++) { if (arr[i].parentId === node.id) { const res = this.convertArrayToTree(arr, arr[i]); if (node.children) { node.children.push(res); } else { node.children = [res]; } } } return node; }, handleNodeClick(data) { let anchorElement = document.getElementById(data.id); let scrollPosition = anchorElement.offsetTop - 20; let myElement = document.getElementById('myElement'); myElement.scrollTo({ left: 0, top: scrollPosition, behavior: 'smooth' }); } } };
3、CSS樣式
.page-api { display: flex; width: 100%; height: 100%; overflow-y: scroll; background-color: #fff; } .api-tree { position: fixed; right: 20px; top: 120px; width: 250px; height: 600px; margin-right: 10px; overflow-y: scroll; /* text-overflow: ellipsis; */ z-index: 99; .el-tree { background: none; color: #686868; .el-tree-node:focus > .el-tree-node__content, .el-tree-node__content:hover { background: none; color: rgb(24, 144, 255); } } } .api-tree::-webkit-scrollbar { width: 8px; } .api-content { flex: 1; width: 80%; margin-left: 20px; margin-right: 220px; padding: 0 30px; h2 { margin-left: 20px; margin-bottom: 10px; } h3 { margin-left: 25px; margin-bottom: 8px; } h4 { margin-left: 30px; margin-bottom: 5px; } li { margin-left: 40px; } code { border-radius: 2px; color: #ffaa7f; margin: 0 2px; padding: 3px 5px; white-space: pre-wrap; } table { border-collapse: collapse; border-spacing: 0; th, td { border: 1px solid #ddd; padding: 6px 13px; margin: 0; } } pre { background: rgba(0, 0, 0, 0.7); padding: 20px 30px; } } .page-api::-webkit-scrollbar { width: 8px; } /* 滾動(dòng)條滑塊樣式 */ .page-api::-webkit-scrollbar-thumb { background-color: #888; /* 設(shè)置滑塊背景顏色 */ border-radius: 4px; /* 設(shè)置滑塊圓角 */ }
4、效果展示
到此這篇關(guān)于使用vue-markdown實(shí)現(xiàn)markdown文件預(yù)覽的文章就介紹到這了,更多相關(guān)vue預(yù)覽markdown內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uni-app獲取當(dāng)前環(huán)境信息的方法
uni-aap提供了異步(uni.getSystemInfo)和同步(uni.getSystemInfoSync)的2個(gè)API獲取系統(tǒng)信息,這篇文章主要介紹了uni-app獲取當(dāng)前環(huán)境信息的相關(guān)知識(shí),需要的朋友可以參考下2022-11-11elementui+vue+axios實(shí)現(xiàn)文件上傳本地服務(wù)器
這篇文章主要為大家詳細(xì)介紹了elementui+vue+axios實(shí)現(xiàn)文件上傳本地服務(wù)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Vue使用lodop實(shí)現(xiàn)打印小結(jié)
這篇文章主要介紹了Vue使用lodop打印小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Vue3?中路由Vue?Router?的使用實(shí)例詳解
vue-router是vue.js官方給出的路由解決方案,能夠輕松的管理SPA項(xiàng)目中組件的切換,這篇文章主要介紹了Vue3?中路由Vue?Router?的使用,需要的朋友可以參考下2023-02-02Vue請(qǐng)求JSON Server服務(wù)器數(shù)據(jù)的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue請(qǐng)求JSON Server服務(wù)器數(shù)據(jù)的實(shí)現(xiàn)方法,需要的朋友可以參考下2018-11-11