1. 安装与核心配置
1.1 安装依赖
bash
npm install highlight.js
1.2 创建高亮工具类 (utils/highlighter.js)
核心要点 :按需注册语言可大幅减少包体积(完整包约 300KB+,按需后通常小于 100KB)。同时需增加 escapeHtml 防止 XSS 攻击。
javascript
// utils/highlighter.js
import hljs from 'highlight.js/lib/core';
// 1. 按需注册常用语言
import javascript from 'highlight.js/lib/languages/javascript';
import typescript from 'highlight.js/lib/languages/typescript';
import xml from 'highlight.js/lib/languages/xml'; // HTML/Vue
import css from 'highlight.js/lib/languages/css';
import json from 'highlight.js/lib/languages/json';
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('typescript', typescript);
hljs.registerLanguage('xml', xml);
hljs.registerLanguage('css', css);
hljs.registerLanguage('json', json);
// 语言别名映射
const langMap = {
'vue': 'xml',
'js': 'javascript',
'ts': 'typescript'
};
// 简单的 HTML 转义(防止 XSS)
function escapeHtml(value) {
return value
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
export default function highlight(code, lang) {
if (!lang) return escapeHtml(code);
const targetLang = langMap[lang] || lang;
try {
if (hljs.getLanguage(targetLang)) {
return hljs.highlight(code, { language: targetLang }).value;
}
} catch (e) {
console.warn('Highlight parsing failed', e);
}
return escapeHtml(code);
}
2. 引入主题样式 (App.vue 或单独 css 文件)
由于小程序不支持动态注入样式,需将 CSS 内容静态引入。推荐从 node_modules/highlight.js/styles/ 选择主题文件。
方法一 :直接在 App.vue 的 <style> 中复制主题内容
方法二:在 main.js 中导入(H5 有效,小程序需额外配置)
javascript
// main.js
import 'highlight.js/styles/atom-one-dark.css';
3. 实现高亮组件 (CodeViewer.vue)
核心思路 :利用 rich-text 组件渲染高亮后的 HTML 字符串。注意行高必须一致才能让行号与代码对齐。
vue
<template>
<view class="code-viewer">
<!-- 横向+纵向滚动 -->
<scroll-view scroll-x scroll-y class="code-scroll">
<view class="code-wrapper">
<!-- 左侧行号列 -->
<view class="line-numbers">
<text v-for="n in lineCount" :key="n" class="line-num">{{ n }}</text>
</view>
<!-- 右侧代码列 (rich-text 渲染) -->
<view class="code-content">
<rich-text :nodes="highlightedHtml" class="code-text"></rich-text>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, toRefs } from 'vue';
import highlight from '@/utils/highlighter';
const props = defineProps({
code: { type: String, default: '' },
lang: { type: String, default: '' }
});
const { code, lang } = toRefs(props);
// 高亮处理:包裹一层 div.hljs.code-body 便于统一样式
const highlightedHtml = computed(() => {
if (!code.value) return '';
const highlighted = highlight(code.value, lang.value);
return `<div class="hljs code-body">${highlighted}</div>`;
});
// 计算行数
const lineCount = computed(() => {
return code.value ? code.value.split('\n').length : 0;
});
</script>
<style scoped>
/* 引入主题样式 - 确保深色/浅色主题路径正确 */
@import url('@/static/code-theme.css');
.code-viewer {
background-color: #282c34;
font-family: 'Consolas', monospace;
font-size: 28rpx;
}
.code-scroll {
width: 100%;
height: 100%;
}
.code-wrapper {
display: flex;
min-width: 100%;
}
/* 行号列 */
.line-numbers {
width: 80rpx;
background-color: #21252b;
color: #636d83;
text-align: right;
padding: 20rpx 10rpx 20rpx 0;
border-right: 1px solid #3b4048;
flex-shrink: 0;
user-select: none;
}
.line-num {
display: block;
height: 40rpx; /* 必须与代码行高一致 */
line-height: 40rpx;
font-size: 24rpx;
}
/* 代码内容区 */
.code-content {
flex: 1;
padding: 20rpx;
}
/* 关键:强制 rich-text 内部的行高与行号列一致 */
:deep(.code-body) {
line-height: 40rpx !important;
white-space: pre;
font-family: inherit;
}
</style>
4. 在页面中使用组件
vue
<template>
<view>
<CodeViewer
:code="exampleCode"
lang="javascript"
/>
</view>
</template>
<script setup>
import CodeViewer from '@/components/CodeViewer.vue';
const exampleCode = `function greet(name) {
console.log("Hello, " + name + "!");
}
greet("uniapp");`;
</script>
5. 进阶方案:直接使用现成插件(推荐)
如果不想手动处理行号和兼容性,可以直接使用 DCloud 插件市场的现成组件:
| 插件名称 | 核心实现 | 特点 |
|---|---|---|
| uaMarkdown | highlight.js | 基于 markdown-it + highlight.js,支持代码块行号,兼容 H5 + 小程序 + App |
| mp-html | 插件机制 | 功能强大的富文本组件,需手动启用 highlight 插件 |
使用示例(uaMarkdown):
vue
<template>
<ua-markdown :source="markdownText" :showLine="true" />
</template>
<script>
import uaMarkdown from '@/components/ua-markdown/ua-markdown.vue';
export default {
components: { uaMarkdown },
data() {
return {
markdownText: '```js\nconsole.log("hello")\n```'
};
}
};
</script>
6. 关键注意事项
-
小程序环境的限制 :无法直接操作 DOM,必须使用
rich-text组件渲染高亮后的 HTML。 -
按需引入 :切勿使用
import hljs from 'highlight.js'(体积过大),应使用lib/core+ 按需注册语言。 -
行高对齐 :
:deep(.code-body)中的line-height必须与行号列的line-height数值完全一致,否则会出现错位。 -
大文件性能:代码超过 5000 行时,可考虑使用 Web Worker 或分片渲染(先显示前 100 行)。
-
vue2 语法差异 :若使用 vue2,需将
script setup改为普通export default,并将:deep()替换为>>>或/deep/。
如果遇到具体平台的报错(如微信开发者工具报 \p 正则不支持),请检查 highlight.js 版本并降级至 10.7.3。