Vue3 使用 highlight.js 实现代码高亮
在博客文章详情页中,代码块是非常常见的内容。
如果只是直接展示普通代码,不仅阅读体验比较差,也不方便快速区分关键字、字符串、注释等内容。
本文使用 highlight.js 为 Vue3 博客文章中的代码块添加语法高亮,并增加 Mac 风格的红黄绿小圆点。
一、安装 highlight.js
首先安装依赖:
npm install highlight.js
二、引入 highlight.js
在文章详情页 article-detail.vue 中引入:
import { ref, onMounted } from 'vue'
import hljs from 'highlight.js'
// 引入代码高亮主题
import 'highlight.js/styles/tokyo-night-dark.css'
这里使用的是:
tokyo-night-dark
主题。
highlight.js 本身提供了很多高亮主题,如果不喜欢这个风格,也可以直接替换成其他 CSS 文件。
三、获取文章正文 DOM
文章正文一般通过 v-html 进行渲染:
<div
ref="articleContentRef"
class="article-content"
v-html="article.content">
</div>
然后定义对应的 ref:
const articleContentRef = ref(null)
这样就可以获取文章正文对应的 DOM 元素。
四、实现代码高亮
由于文章内容可能是异步加载后再渲染到页面中的,因此这里使用 MutationObserver 监听正文 DOM 的变化。
onMounted(() => {
const observer = new MutationObserver(() => {
const codeBlocks = document.querySelectorAll('pre code')
codeBlocks.forEach(block => {
hljs.highlightBlock(block)
})
})
observer.observe(articleContentRef.value, {
childList: true,
subtree: true
})
})
核心逻辑其实很简单。
首先获取所有代码块:
document.querySelectorAll('pre code')
然后遍历代码块:
codeBlocks.forEach(block => {
hljs.highlightBlock(block)
})
最终 highlight.js 就会自动识别代码并添加对应的高亮样式。
例如文章 Markdown 中存在:
@Test
void testLog() {
log.info("这是一行 Info 级别日志");
log.warn("这是一行 Warn 级别日志");
log.error("这是一行 Error 级别日志");
String author = "犬小哈";
log.info("作者:{}", author);
}
渲染到页面后,就会自动显示代码高亮效果。
五、解决行内 code 样式冲突
博客正文中通常还会存在行内代码,例如:
<code>npm install</code>
如果之前已经给所有 code 标签设置了样式,就可能覆盖 highlight.js 自带的代码块样式。
可以修改为:
::v-deep(.article-content code:not(pre code)) {
padding: 2px 4px;
margin: 0 2px;
font-size: 95% !important;
border-radius: 4px;
color: rgb(41, 128, 185);
background-color: rgba(27, 31, 35, 0.05);
font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;
}
关键代码是:
code:not(pre code)
它的作用是:
只给普通的行内 code 设置样式,不影响 pre 中的代码块。
这样两种代码样式就可以互不干扰。
六、添加 Mac 风格红黄绿小圆点
为了让代码块更加美观,可以在代码块顶部增加三个小圆点。
添加下面的样式:
::v-deep(code) {
font-size: 98%;
}
::v-deep(pre) {
position: relative;
margin-bottom: 20px;
}
::v-deep(pre code.hljs) {
padding: 2rem 1rem 0.7rem;
border-radius: 6px;
}
::v-deep(pre::before) {
content: '';
position: absolute;
z-index: 1;
width: 10px;
height: 10px;
margin-top: 10px;
margin-left: 10px;
border-radius: 50%;
background: #fc625d;
box-shadow:
20px 0 #fdbc40,
40px 0 #35cd4b;
}
这里并没有真正创建三个 DOM 元素。
实际上只创建了一个红色圆点:
background: #fc625d;
然后利用:
box-shadow
生成黄色和绿色两个圆点:
box-shadow:
20px 0 #fdbc40,
40px 0 #35cd4b;
这样就能实现类似 Mac 窗口顶部的红黄绿按钮效果。
七、核心代码
最终核心代码如下:
<template>
<div
ref="articleContentRef"
class="article-content"
v-html="article.content">
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import hljs from 'highlight.js'
import 'highlight.js/styles/tokyo-night-dark.css'
const articleContentRef = ref(null)
onMounted(() => {
const observer = new MutationObserver(() => {
document.querySelectorAll('pre code').forEach(block => {
hljs.highlightBlock(block)
})
})
observer.observe(articleContentRef.value, {
childList: true,
subtree: true
})
})
</script>
八、总结
通过 highlight.js,可以非常方便地给 Vue3 博客文章中的代码块增加语法高亮。
整个实现主要分为三步:
- 安装并引入 highlight.js;
- 找到文章中的
pre code元素并执行高亮; - 添加自定义 CSS,美化代码块样式。
对于技术博客来说,代码块的阅读体验还是非常重要的。
加上高亮和红黄绿小圆点之后,整体效果会比普通代码块更加美观。