摘要
本文将带你全面掌握如何在 Vue2 项目中使用 vue-markdown
组件,实现 Markdown 文本的解析与渲染。涵盖:
- ✅
vue-markdown
简介与安装 - ✅ 基础用法与核心属性
- ✅ 高级功能(自定义样式、扩展语法)
- ✅ 安全性处理(XSS 防护)
- ✅ 实战案例:构建一个 Markdown 编辑预览器
- ✅ 替代方案与未来展望
一、什么是 vue-markdown
?
vue-markdown
是一个基于 marked.js 的 Vue 组件,用于在 Vue 应用中轻松渲染 Markdown 格式的文本。
核心特点
- 简单易用 :通过
<vue-markdown>
标签即可渲染 Markdown。 - 轻量级 :依赖
marked
,体积小,性能好。 - 可定制:支持自定义标签、样式、扩展语法等。
- Vue 友好:作为 Vue 组件集成,与 Vue 生态无缝衔接。
⚠️ 注意 :
vue-markdown
项目在 GitHub 上已不再积极维护。但对于 Vue2 项目,它仍然是一个稳定、可靠的选择。对于新项目,建议考虑## Md-editor-v3
或其他现代方案。
二、环境准备与安装
2.1 前提条件
- 已安装 Node.js 和 npm/yarn
- 已创建 Vue2 项目(可通过 Vue CLI 创建)
bash
vue create vue-markdown-demo
# 选择 Vue 2 preset
cd vue-markdown-demo
2.2 安装 vue-markdown
bash
npm install vue-markdown --save
# 或
yarn add vue-markdown
依赖说明 :
vue-markdown
依赖marked
,安装时会自动安装。
三、基础用法
3.1 全局注册组件
在 main.js
中全局注册 vue-markdown
:
javascript
import Vue from 'vue'
import App from './App.vue'
import VueMarkdown from 'vue-markdown'
// 全局注册组件
Vue.component('vue-markdown', VueMarkdown)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
3.2 在组件中使用
创建 MarkdownDemo.vue
:
vue
<template>
<div class="markdown-demo">
<h2>Markdown 基础示例</h2>
<!-- 直接传入 Markdown 字符串 -->
<vue-markdown>
# 这是一个标题
这是一个段落,支持 **加粗** 和 *斜体*。
- 列表项 1
- 列表项 2
</vue-markdown>
</div>
</template>
<script>
import VueMarkdown from 'vue-markdown'
export default {
name: 'MarkdownDemo',
components: {
VueMarkdown
}
}
</script>
<style scoped>
.markdown-demo {
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
margin: 20px;
}
</style>
3.3 动态渲染
通过 v-model
或 :source
属性动态渲染 Markdown:
vue
<template>
<div class="dynamic-markdown">
<textarea v-model="markdownText" placeholder="输入 Markdown..." rows="10"></textarea>
<h3>预览:</h3>
<vue-markdown :source="markdownText" />
</div>
</template>
<script>
export default {
data() {
return {
markdownText: '# 动态 Markdown\n\n实时预览你的输入。'
}
}
}
</script>
四、核心属性详解
vue-markdown
提供了丰富的属性来自定义渲染行为。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
source |
String | '' |
要渲染的 Markdown 源文本 |
tag |
String | 'div' |
外层包裹的 HTML 标签 |
html |
Boolean | false |
是否解析 Markdown 中的 HTML 标签 |
langPrefix |
String | 'language-' |
代码块语言的 CSS 类前缀 |
linkify |
Boolean | true |
将文本中的 URL 自动转换为链接 |
typographer |
Boolean | false |
启用一些语言相关的破折号替换 |
breaks |
Boolean | false |
转换 \n 为 <br> |
inline |
Boolean | false |
是否作为内联元素渲染(不包裹 <p> ) |
anchorAttributes |
Object | {} |
为生成的锚点(<a> )添加自定义属性 |
示例:启用 HTML 和链接自动转换
vue
<vue-markdown
:source="content"
:html="true"
:linkify="true"
:breaks="true"
tag="article">
</vue-markdown>
五、高级功能与扩展
5.1 自定义样式
vue-markdown
渲染出的 HTML 元素带有标准的语义化标签(h1
, p
, ul
, pre code
等),你可以通过 CSS 轻松定制样式。
css
/* 自定义 Markdown 样式 */
.vue-markdown h1 {
color: #1890ff;
border-bottom: 2px solid #eee;
}
.vue-markdown code {
background: #f5f5f5;
padding: 2px 4px;
border-radius: 3px;
font-family: 'Courier New', monospace;
}
.vue-markdown pre {
background: #2b2b2b;
color: #f8f8f2;
padding: 16px;
overflow: auto;
border-radius: 6px;
}
.vue-markdown pre code {
background: none;
color: inherit;
font-size: 14px;
}
5.2 扩展语法(使用 marked
配置)
虽然 vue-markdown
本身不直接暴露 marked
的所有配置,但你可以通过修改 marked
的全局设置来扩展功能。
javascript
import marked from 'marked';
// 配置 marked
marked.setOptions({
highlight: function(code, lang) {
// 集成代码高亮(需引入 highlight.js)
if (lang && window.hljs) {
try {
return window.hljs.highlight(lang, code).value;
} catch (err) {
console.error('Highlight error:', err);
}
}
return code; // use external default escaping
},
// 其他选项...
});
然后在 vue-markdown
外部引入 highlight.js
:
html
<!-- public/index.html -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
5.3 安全性:防范 XSS 攻击
如果启用了 :html="true"
,用户输入的 HTML 可能包含恶意脚本(XSS)。强烈建议 对用户输入的内容进行严格的过滤或使用专门的库(如 DOMPurify
)进行净化。
bash
npm install dompurify
javascript
import DOMPurify from 'dompurify';
// 在渲染前净化 HTML
const cleanHTML = DOMPurify.sanitize(dirtyHTML);
最佳实践 :除非必要,否则不要开启
:html="true"
。对于用户生成内容,始终进行输入验证和输出净化。
六、实战案例:Markdown 编辑预览器
我们将构建一个完整的 Markdown 编辑器,支持实时预览。
6.1 项目结构
css
src/
├── components/
│ ├── MarkdownEditor.vue
│ └── MarkdownPreview.vue
└── views/
└── EditorView.vue
6.2 编辑器组件 (MarkdownEditor.vue
)
vue
<template>
<textarea
v-model="content"
@input="onInput"
class="markdown-editor"
placeholder="输入 Markdown 语法..."
></textarea>
</template>
<script>
export default {
name: 'MarkdownEditor',
props: {
value: String
},
data() {
return {
content: this.value || ''
}
},
methods: {
onInput() {
this.$emit('input', this.content);
}
}
}
</script>
<style scoped>
.markdown-editor {
width: 100%;
height: 300px;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-family: 'Monaco', 'Consolas', monospace;
resize: vertical;
}
</style>
6.3 预览组件 (MarkdownPreview.vue
)
vue
<template>
<div class="markdown-preview">
<vue-markdown
:source="source"
:html="false"
:breaks="true"
:linkify="true"
/>
</div>
</template>
<script>
import VueMarkdown from 'vue-markdown'
export default {
name: 'MarkdownPreview',
components: { VueMarkdown },
props: {
source: String
}
}
</script>
<style scoped>
.markdown-preview {
padding: 20px;
border: 1px solid #eee;
border-radius: 6px;
background: #fff;
min-height: 300px;
/* 引入前面定义的 Markdown 样式 */
}
</style>
6.4 主视图 (EditorView.vue
)
vue
<template>
<div class="editor-view">
<h1>Markdown 实时编辑器</h1>
<div class="editor-container">
<div class="editor-pane">
<h3>编辑</h3>
<MarkdownEditor v-model="markdownContent" />
</div>
<div class="preview-pane">
<h3>预览</h3>
<MarkdownPreview :source="markdownContent" />
</div>
</div>
</div>
</template>
<script>
import MarkdownEditor from '@/components/MarkdownEditor.vue'
import MarkdownPreview from '@/components/MarkdownPreview.vue'
export default {
name: 'EditorView',
components: {
MarkdownEditor,
MarkdownPreview
},
data() {
return {
markdownContent: `# 欢迎使用 Markdown 编辑器
## 功能列表
- **实时预览**
- 支持标准 Markdown 语法
- 代码块高亮(需配置)
\`\`\`javascript
function hello() {
console.log("Hello, Markdown!");
}
\`\`\`
[访问 Vue 官网](https://vuejs.org)`
}
}
}
</script>
<style scoped>
.editor-view {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.editor-container {
display: flex;
gap: 20px;
margin-top: 20px;
}
.editor-pane, .preview-pane {
flex: 1;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.editor-pane h3, .preview-pane h3 {
margin: 0;
padding: 10px;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.preview-pane {
background: #fafafa;
}
</style>
参考资料
vue-markdown
GitHub: github.com/miaolz123/v...marked.js
官方文档: marked.js.org/DOMPurify
: github.com/cure53/DOMP...highlight.js
: highlightjs.org/
欢迎点赞、收藏、分享!如有疑问或建议,欢迎在评论区留言交流。