Vue2 怎么实现 Markdown 渲染?从基础到进阶全解析
在 Vue2 项目里做博客、文档系统,或者让用户用 Markdown 写内容时,怎么把 Markdown 文本转成好看的 HTML 展示?这篇文章从“选啥工具”“咋基础实现”到“进阶优化”,一步步讲清楚 Vue2 里 Markdown 渲染的门道~
Vue2 项目里为啥要做 Markdown 渲染?
你想啊,现在很多场景都需要 Markdown:团队内部写技术文档,用 Markdown 更高效;做个人博客,写文章用 Markdown 排版省心;甚至社区论坛让用户发帖,用 Markdown 能避免复杂的富文本操作,但浏览器不认识 Markdown 语法啊,得把它转成 HTML 才能正常显示样式,Vue2 项目里得做“Markdown 转 HTML 并渲染”这件事,既让内容创作者写得爽,也让读者看得舒服。
Vue2 常用的 Markdown 渲染库有哪些?
常用的有三类,各有特点:
- marked.js:轻量级选手,API 简单,上手快,适合只需要“把 Markdown 转成 HTML”的基础需求,比如简单文档展示,体积小,不拖项目后腿。
- markdown-it:扩展性狂魔,生态里插件超级多(代码高亮、生成目录、流程图解析…),如果项目需要复杂功能,选它准没错。
- vue-markdown:Vue 专用组件,把 Markdown 渲染封装成组件,直接在模板里用
<vue-markdown>
标签就行,适合想少写代码、快速集成的场景。
怎么选适合自己项目的 Markdown 渲染方案?
得看项目需求和团队情况:
- 需求简单(只渲染标题、列表、段落):选 marked.js,体积小、配置少,几行代码就能跑起来。
- 需求复杂(要代码高亮、自定义语法、图片/链接处理):选 markdown-it,靠插件扩展功能,想加啥功能都能找到现成的。
- 想少写代码:用 vue-markdown 组件,开箱即用,连
v-html
都不用自己写,但如果后期要深度定制,可能没 markdown-it 灵活。
另外还要考虑项目体积(marked.js 比 markdown-it 小)、团队技术熟练度(比如团队熟悉 Vue 组件写法,就优先 vue-markdown)这些因素。
Vue2 里用 marked.js 实现基础渲染步骤是啥?
分三步,还要注意 XSS 风险:
- 装依赖:终端执行
npm install marked
。 - 组件里用 marked:在 Vue 组件中引入 marked,写个方法把 Markdown 字符串转成 HTML。
<template> <div v-html="renderedHtml"></div> </template>
用 markdown-it 怎么实现更灵活的渲染(比如代码高亮)?
markdown-it 本身不自带代码高亮,得结合 highlight.js
这类库,步骤如下:
- 装依赖:
npm install markdown-it highlight.js
。 - 配置 markdown-it 和代码高亮:在组件里创建 markdown-it 实例,设置代码高亮的逻辑。
<template> <div v-html="renderedHtml"></div> </template>
Vue 专用组件 vue-markdown 怎么快速集成?
适合想“零配置”用起来的同学,步骤很简单:
- 装依赖:
npm install vue-markdown
。 - 组件里用:引入后当普通 Vue 组件用,直接传 Markdown 内容。
<template> <vue-markdown :source="markdownContent" :options="{ highlight: myHighlight }"></vue-markdown> </template>
Markdown 渲染后的样式怎么自定义?
分两种情况:库默认样式和自己写 CSS。
- 像 marked.js、markdown-it 这类库,默认渲染出的 HTML 是“裸”的,没有样式,得自己写 CSS 美化,比如给标题、列表、代码块加样式:
/* 全局的 markdown 样式文件 */ .markdown h1 { font-size: 28px; margin-bottom: 16px; color: #333; } .markdown p { line-height: 1.8; margin: 8px 0; } .markdown code { background: #f9f9f9; padding: 2px 4px; border-radius: 4px; }
然后在渲染的容器上加
class="markdown"
,让样式生效。 - 如果用了代码高亮(highlight.js),它的样式由引入的主题决定(
atom-one-light.css
),要是觉得主题不好看,可以自己写 CSS 覆盖.hljs
开头的类名。
在 Vue 组件里写样式时,如果用了<style scoped>
,要修改子组件或第三方库的样式,得用深度选择器,<style scoped> .my-markdown >>> h2 { color: #444; } </style>
处理 Markdown 里的图片、链接有啥技巧?
图片处理
- 统一加路径前缀:Markdown 里的图片是相对路径,想转成 CDN 地址,可以在渲染前替换字符串。
const rawMd = '' const cdnMd = rawMd.replace(/!\[(.+?)\]\((images\/.+?)\)/g, '')
- 用 markdown-it 插件:
markdown-it-linkify-images
能自动给图片加链接,或者写自定义渲染规则,修改图片标签的生成逻辑。
链接处理
- 外部链接开新窗口:用户点外部链接时,希望在新窗口打开,还得加
rel="noopener noreferrer"
防止安全问题,用 markdown-it 重写链接的渲染规则:import md from 'markdown-it' const renderer = md() // 重写 link_open 规则 const defaultLinkRender = renderer.renderer.rules.link_open || function(tokens, idx, opts, env, self) { return self.renderToken(tokens, idx, opts) } renderer.renderer.rules.link_open = function(tokens, idx, opts, env, self) { const href = tokens[idx].attrGet('href') if (href && href.startsWith('http')) { // 判断是否外部链接 tokens[idx].attrSet('target', '_blank') tokens[idx].attrSet('rel', 'noopener noreferrer') } return defaultLinkRender(tokens, idx, opts, env, self) }
这样渲染出来的外部链接,自动带
target="_blank"
和安全属性。
Vue2 Markdown 渲染遇到 XSS 攻击风险咋解决?
前面提过用 DOMPurify
过滤,这里再详细说场景和配置。
- 场景:Markdown 内容是用户生成的(比如论坛发帖),恶意用户可能在 Markdown 里写
<script>alert(1)</script>
,转成 HTML 后会执行脚本。 - 解决步骤:
- 装
DOMPurify
:npm install dompurify
。 - 在 Markdown 转 HTML 后,用
DOMPurify
净化:import DOMPurify from 'dompurify' // 假设 html 是 Markdown 转后的 HTML 字符串 const cleanHtml = DOMPurify.sanitize(html)
- 高级配置:如果想允许某些标签/属性(比如自己项目里需要
<iframe>
嵌入视频),可以自定义配置:const config = { ALLOWED_TAGS: ['iframe', 'img', 'p', 'h1', 'h2'], // 允许的标签 ALLOWED_ATTR: { iframe: ['src', 'width', 'height'] // 允许 iframe 的属性 } } const cleanHtml = DOMPurify.sanitize(html, config)
这样既保留业务需要的标签,又过滤危险内容。
- 装
大型项目里 Markdown 渲染的性能优化怎么做?
Markdown 内容特别长(比如几万字的文档),解析和渲染会变慢,得优化:
- 缓存解析结果:用
computed
或vuex
缓存解析后的 HTML,相同内容不重复解析。computed: { renderedHtml() { if (this.cache[markdownContent]) { return this.cache[markdownContent] } const html = md.render(markdownContent) this.cache[markdownContent] = html return html } }
- 异步解析:把 Markdown 解析放到
setTimeout
或 Web Worker 里,避免阻塞主线程,比如用 Web Worker:// main.js const worker = new Worker('markdown-worker.js') worker.postMessage(markdownContent) worker.onmessage = (e) => { this.renderedHtml = e.data }
// markdown-worker.js importScripts('path/to/markdown-it.js') const md = require('markdown-it')() self.onmessage = (e) => { const html = md.render(e.data) self.postMessage(html) }
- **分片渲染**:如果内容超长,把 HTML 分成多段,用 `v-if` 分批渲染,减少首屏加载压力。
### Vue2 升级到 Vue3 后 Markdown 渲染有啥变化?
核心的 Markdown 解析库(marked、markdown-it)用法不变,但 Vue 组件写法有变化:
- **Composition API**:Vue3 用 `setup` 语法糖,代码组织更集中,比如用 markdown-it 时,逻辑可以写到 `setup` 里:
```vue
<script setup>
import md from 'markdown-it'
import { computed } from 'vue'
const markdownContent = '# Vue3 里的 Markdown'
const renderedHtml = computed(() => md().render(markdownContent))
</script>
<template>
<div v-html="renderedHtml"></div>
</template>
- 组件兼容性:如果之前用
vue-markdown
,Vue3 得换对应的库(vue3-markdown
),要注意版本兼容。
Markdown 渲染的“逻辑”没变,只是 Vue 组件的写法更灵活了。
从选库到基础实现,再到样式、安全、性能这些细节,Vue2 里做 Markdown 渲染其实没那么复杂~根据自己项目需求挑对工具,再把细节(XSS、代码高亮)处理好,用户就能舒舒服服写 Markdown,读者也能看到美观的排版啦~要是你在实践中遇到其他问题,比如插件怎么自定义、移动端样式适配,评论区聊聊呀~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。