vue/react 中实现 markdown 文件解析+目录(vue教程)
前言
最近有一个需求要把markdown文件展示到页面中,并且带目录。看了一些插件,把实践方法记录一下。
目标:
把 markdown 文件展示到页面中。
要根据标题展示 markdown 目录。
要有一些简单美观的 markdown 样式。
先介绍一下这些插件:
marked 只用于解析 Markdown,无样式,无目录。
highlight.js 用于代码颜色高亮
markdown-navbar 用于生成目录,适用于react
github-markdown-css github 风格的 markdown 样式
vue-markdown 适用于 Vue 的强大且高速的 Markdown 解析器。有样式有目录。
最开始想到的是用 marked + highlight.js 实现,但是 marked 插件无法生成目录,目录需要再用 markdown-navbar 插件辅助实现。然而 markdown-navbar 仅适用于 react 。所以我这里会写两种方法:
方法一:在 react项目中 用 marked + highlight.js + markdown-navbar 实现解析+目录。
方法二:在 vue项目中 用 vue-markdown 实现解析+目录。
虽然 vue-markdown 自带样式,但是我觉得 github-markdown-css 的样式顺眼一点,所以这两种方法中都是用的 github-markdown-css 样式。
marked + highlight.js + markdown-navbar
先看一下实现效果:
其实 markdown-navbar 这个插件生成的目录非常完美,奈何只能用于 react 。marked 和 highlight.js 哪里都可以用没有限制,可以外链,可以npm。
github-markdown-css 文件我是直接放的css外链,当然也可以使用npm的方式添加。
注意:页面结构样式还是需要自己写的。
代码如下:
import React, { Component } from 'react'; import './App.css'; import ReactMarkdown from 'react-markdown'; import MarkNav from 'markdown-navbar'; import 'markdown-navbar/dist/navbar.css'; class App extends Component { constructor(props) { super(props) this.state = { markdown: '' } } render() { return ( <div className="App"> <div className="leftSide"> <h3 className="navTitle">文章目录</h3> <MarkNav className="toc-list" source={this.state.markdown} ordered={false} /> </div> <div className="content"> <div className="inputDv"> <input type="file" accept=".md" onChange={this.getFileInfo.bind(this)} /> </div> <div className="markdown-body"> <ReactMarkdown children={this.state.markdown} escapeHtml={false} /> </div> </div> </div> ); } getFileInfo(event){ let _that = this; // 获取 input file 对象 const resultFile = event.target.files[0]; if(resultFile){ // 使用 FileReader 方法读取文件 let reader = new FileReader(); // 读取纯文本文件,且编码格式为 utf-8 reader.readAsText(resultFile, 'UTF-8'); // 读取文件,会触发 onload 异步事件,可使用回调函数来获取最终的值 reader.onload = function (e) { _that.setState({ markdown:e.target.result }) } } } } export default App; 复制代码
vue-markdown
官方效果地址:VueMarkdown Live Demo
实现效果如下:
vue-markdown 这个插件功能还是挺全面的,有目录有样式,但是目录那块,没有 markdown-navbar 的功能那么全面,比如点击没有高亮样式,也不能随着滚动切换高亮效果,也有可能是我文档没看明白,文档中有很多选项,有兴趣的小伙伴可以自己去看一下文档。
代码如下:
<!DOCTYPE html> <html> <head> <title>vue-markdown</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- github-markdown-css markdown 样式 --> <link rel="stylesheet" href="https://unpkg.com/github-markdown-css@5.0.0/github-markdown.css"> <!-- 自定义布局样式 --> <link rel="stylesheet" href="../css/markdown.css"> </head> <body> <div id="app"> <div class="left-navSide"> <h3 class="nav-title">文章目录</h3> <div class="nav-list" id="toc"></div> </div> <div class="right-content markdown-body"> <vue-markdown :source="source" :toc="true" toc-id="toc" :toc-first-level="2" :toc-last-level="3" v-on:toc-rendered="tocAllRight" /> </div> </div> <script src="https://miaolz123.github.io/vue-markdown/dist/js/vue.js"></script> <script src="https://miaolz123.github.io/vue-markdown/dist/vue-markdown.min.js"></script> <script> Vue.use(VueMarkdown) let vm = new Vue({ el:'#app', data() { return { source:'', } }, created:function(){ this.loadXMLDoc() }, methods:{ loadXMLDoc(){ var $this = this; var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { // console.log(xmlhttp.responseText) $this.source = xmlhttp.responseText; } } xmlhttp.open("GET","../file/test.md",true); xmlhttp.send(); } } }) </script> </body> </html> 复制代码
结语
总结一下,如果不需要目录,直接用 marked 解析 markdown,github-markdown-css 作样式就可以了。
如果需要目录,react 中 markdown-navbar 的目录功能能全面。vue 中 vue-markdown 这一个插件就足够了,目录和样式他都有,只是目前来看细节的地方不是那么完善,但是也够用了。
以上这些插件和实现效果是我尝试过的,当然还有其他插件可以实现同等的效果,欢迎探讨。
作者:1023
链接:https://juejin.cn/post/7028826246616350728