Code前端首页关于Code前端联系我们

Vue2 集成 markdown-it 要做哪些准备?

terry 5小时前 阅读数 6 #Vue
文章标签 it

做技术项目时,经常碰到要把 Markdown 文本转成美观 HTML 展示的需求,比如博客文章、组件文档、帮助中心这些场景,Vue2 项目里想实现这功能,markdown-it 是个很趁手的工具,但不少同学刚接触时,会纠结“咋把 markdown-it 加到 Vue2 里?配置、插件、样式这些咋处理?” 下面用问答形式,把 Vue2 + markdown-it 从基础到进阶的知识点拆解开讲~

首先得把工具链搭起来,第一步是安装依赖,打开终端,在 Vue2 项目根目录执行 `npm install markdown-it`(用 yarn 就换 `yarn add markdown-it`),这一步是把 markdown-it 这个库拉到项目里,它能帮我们把 Markdown 语法解析成 HTML 字符串。

然后得理解 markdown-it 的核心逻辑:它本质是个解析器,初始化一个实例后,调用 render 方法传入 Markdown 文本,就能得到对应的 HTML,所以在 Vue 组件里,我们要做的是 —— 引入库、初始化实例、调用解析方法。

举个简单例子,新建个组件,在 <script> 里引入:

import MarkdownIt from 'markdown-it'
export default {
  data() {
    return {
      mdText: '## 这是个测试标题\n**加粗内容**' // 模拟从接口或编辑器拿到的 Markdown 内容
    }
  },
  methods: {
    renderMd() {
      const md = new MarkdownIt() // 初始化解析器实例
      return md.render(this.mdText) // 把 Markdown 转成 HTML
    }
  }
}

这样就完成了最基础的“引入 - 初始化 - 解析”流程,不过实际项目里,为了性能和代码整洁,一般会把解析逻辑放到 computed 或者封装成工具函数,后面展开讲~

怎么在 Vue2 组件里渲染 Markdown 内容到页面?

核心是“解析 + 安全渲染”两步走。

第一步:解析 Markdown 成 HTML

刚才提到用 markdownIt.render() 能生成 HTML 字符串,但直接写在方法里每次调用都新建实例,有点浪费性能,更优的做法是在 mounted 里初始化实例,存到 data 里复用:

export default {
  data() {
    return {
      md: null, // 存 markdown-it 实例
      mdText: '# 我的第一篇 Vue2 + Markdown 文章',
      renderedHtml: '' // 存解析后的 HTML
    }
  },
  mounted() {
    this.md = new MarkdownIt() // 初始化实例,可配置参数
    this.renderedHtml = this.md.render(this.mdText)
  }
}

第二步:用 v-html 渲染到页面

Vue 里渲染 HTML 字符串得用 v-html 指令,所以模板里写:

<template>
  <div class="markdown-container" v-html="renderedHtml"></div>
</template>

必须注意安全问题!Markdown 内容来自用户输入(比如开放编辑器),直接渲染可能被注入 XSS 攻击(比如用户写 <script>alert(1)</script> 这种代码),这时候建议结合 DOMPurify 这类库,先过滤危险标签再渲染,步骤是:

  1. 安装 DOMPurifynpm install dompurify
  2. 引入后过滤 HTML:
    import DOMPurify from 'dompurify'
    // 解析后过滤
    const cleanHtml = DOMPurify.sanitize(md.render(this.mdText))
    this.renderedHtml = cleanHtml

markdown-it 常用配置有哪些?能解决啥问题?

markdown-it 初始化时可以传配置对象,调整解析规则和渲染行为,常见需求对应配置如下:

控制 HTML 标签是否转义

默认 html: false,意思是 Markdown 里写的 HTML 标签会被转义(<div> 变成 &lt;div&gt;),如果想让 Markdown 里的 HTML 直接生效(比如写自定义组件 <MyComponent />),得开 html: true

new MarkdownIt({ html: true })

让换行符转成 <br>

默认 Markdown 里的换行(\n)不会转成 <br>,得敲两个空格 + 换行才生效,如果想让单换行也转 <br>,开 breaks: true

new MarkdownIt({ breaks: true })

自动加 ID(做锚点用) # 标题)渲染后是 <h1>标题</h1>,没 ID 不好做锚点跳转,可以通过配置 headingIds: true 让标题自动生成 ID(基于内容):

new MarkdownIt({ headingIds: true })
// 渲染后:<h1 id="标题">标题</h1>(实际会做 slug 处理,比如中文转拼音或保留字符)

代码块高亮(结合 highlight.js)

想让代码块带语法高亮,得配合 highlight.js,步骤:

  1. 安装 highlight.jsnpm install highlight.js
  2. 初始化时配置高亮函数:
    import hljs from 'highlight.js'
    new MarkdownIt({
    highlight: function (str, lang) {
     if (lang && hljs.getLanguage(lang)) {
       try {
         return hljs.highlight(str, { language: lang }).value
       } catch (err) {}
     }
     return '' // 没匹配到语言,返回空(或默认处理)
    }
    })

    这样代码块 <pre><code> 会被加上高亮样式,再引入 highlight.js 的主题 CSS(import 'highlight.js/styles/atom-one-light.css'),就能实现美观的代码高亮。

想给 markdown-it 加插件扩展功能,咋操作?

markdown-it 生态有很多实用插件,比如生成目录、加锚点、优化表格渲染等,以标题锚点(markdown-it-anchor)目录生成(markdown-it-table-of-contents)为例,看怎么集成:

案例 1:给标题加锚点(markdown-it-anchor)

  1. 安装插件:npm install markdown-it-anchor
  2. 引入并注册到 markdown-it 实例:
    import MarkdownIt from 'markdown-it'
    import anchor from 'markdown-it-anchor'

const md = new MarkdownIt() md.use(anchor, { permalink: true, // 显示锚点链接(小图标或链接) permalinkSymbol: '#' // 锚点符号,也可以用 FontAwesome 图标 }) ``会变成

#`,点锚点能跳转到对应位置。

案例 2:生成文章目录(markdown-it-table-of-contents)

  1. 安装插件:npm install markdown-it-table-of-contents
  2. 注册并配置:
    import toc from 'markdown-it-table-of-contents'

md.use(toc, { includeLevel: [1, 2, 3], // 包含 h1 - h3 标题 headingText: '文章目录' // 目录标题文字 })

然后在 Markdown 里写 `[toc]` 关键词,渲染后会自动生成目录列表。  
### Vue2 里 markdown-it 渲染的内容没样式,咋解决?  
Markdown 转成 HTML 后,默认是“裸”标签(只有语义,没样式),得自己加 CSS,有两种思路:  
#### 思路 1:自己写样式  
给常见标签(`h1 - h6`、`p`、`ul/ol`、`code`、`pre`、`blockquote` 等)写样式。  
```css
.markdown-container h1 {
  font-size: 28px;
  margin-bottom: 16px;
  border-bottom: 1px solid #eee;
  padding-bottom: 8px;
}
.markdown-container code {
  background: #f5f5f5;
  padding: 2px 4px;
  border-radius: 4px;
}
/* 其他标签... */

好处是完全自定义,贴合项目风格;缺点是要写很多代码,对新手不友好。

思路 2:用现成样式库

最火的是 github-markdown-css,它模拟 GitHub 上 Markdown 渲染的样式,开箱即用,步骤:

  1. 安装:npm install github-markdown-css
  2. 引入样式:
    import 'github-markdown-css'
  3. 给渲染容器加类名:
    <div class="markdown-body" v-html="renderedHtml"></div>

    这样渲染出的内容直接继承 GitHub 风格,省了写样式的功夫,类似的还有 markdown-css-themes 这类库,提供多种预设主题,按需选择就行。

大量 Markdown 内容渲染,性能咋优化?

如果页面要渲染几万字的 Markdown(比如长文档),直接解析+渲染可能卡页面,可以从这几点优化:

缓存解析结果

Markdown 内容不变(比如静态文章),把解析后的 HTML 存起来,避免重复解析,用 computed + 缓存逻辑:

computed: {
  renderedHtml() {
    if (this.cacheHtml) return this.cacheHtml
    const html = this.md.render(this.mdText)
    this.cacheHtml = html // 存到 data 里
    return html
  }
}

防抖 + 异步渲染(针对实时预览场景)

如果做“编辑器实时预览”(比如左边输入,右边实时更行),输入时频繁解析会很卡,用 lodash.debounce 防抖,延迟解析:

import { debounce } from 'lodash'
export default {
  data() {
    return {
      mdText: '',
      renderedHtml: ''
    }
  },
  methods: {
    handleInput: debounce(function (val) {
      this.renderedHtml = this.md.render(val)
    }, 300) // 输入停止 300ms 后再解析
  }
}

模板里绑定输入事件:

<textarea v-model="mdText" @input="handleInput($event.target.value)"></textarea>

分片渲染长内容 极长(比如几万行),一次性插入 DOM 会阻塞渲染,可以把 HTML 拆成小块,用 requestAnimationFrame 分批插入,类似虚拟列表思路,不过这对 Vue2 来说稍复杂,小项目一般用前两种方法就够。

和其他富文本方案比,markdown-it 在 Vue2 里有啥独特优势?

常见富文本方案有 Quill、TinyMCE、Slate 等,和它们比,markdown-it 适合场景,优势很明显:

  • 轻量灵活:核心库才几十 KB,加载快;插件按需引入,不会冗余。
  • 学习成本低:只要懂 Markdown 语法(程序员基本都熟),不需要学复杂的富文本编辑器操作(比如选字体、调格式)。
  • 扩展性强:插件生态丰富,从代码高亮到流程图渲染(markdown-it-mermaid),想加功能只需要装插件+配置。
  • 版本稳定:Vue2 已经是成熟框架,markdown-it 也迭代多年,兼容性和稳定性经过大量项目验证。

比如做开源组件文档站、个人技术博客,用 markdown-it 配合 Vue2 快速搭起“写 Markdown -> 解析 -> 美观展示”的流程,比用重型富文本编辑器效率高太多。

实际项目里,Vue2 + markdown-it 有哪些避坑点?

踩过这些“坑”,能少走弯路:

v-html 的 XSS 风险

前面提过,用户输入的内容必须过滤!哪怕是内部系统,也别偷懒,用 DOMPurify 这类库过滤后再渲染,避免脚本注入。

插件版本兼容问题

不同 markdown-it 版本对插件的支持可能不同,markdown-it@13.x 和某些老插件不兼容,装插件前看 npm 文档里的版本要求,或者直接看 GitHub 仓库的 README。

自定义渲染器时破坏默认逻辑

如果要自定义某类标签的渲染(比如把所有 <a> 改成带 target="_blank"),需要懂 markdown-it 的 Renderer 机制,直接改 renderer.rules 时,要保留原逻辑再扩展,否则可能导致解析错误,示例:

const md = new MarkdownIt()
// 自定义链接渲染,保留原逻辑并加 target
const defaultLinkRender = md.renderer.rules.link_open
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
  tokens[idx].attrPush(['target', '_blank']) // 加属性
  return defaultLinkRender(tokens, idx, options, env, self) // 调用默认渲染
}

样式冲突

如果项目里有全局样式(比如重置样式 normalize.css),可能和 markdown 渲染的标签样式冲突,建议给渲染容器加独特类名(class="md-render"),然后用后代选择器写样式(.md-render h1 { ... }),隔离样式作用域。

从基础集成到性能优化,再到插件拓展和避坑,Vue2 里用 markdown-it 实现 Markdown 渲染的核心点基本覆盖啦~ 实际项目里,根据需求选配置、挑插件、搭样式,就能快速做出“写 Markdown 像写笔记,渲染后像专业文档”的效果,要是你在开发文档系统、技术博客这类项目,不妨试试这套组合,轻量化又灵活,能省不少开发时间~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门