CodeBlock 代码块
代码高亮、行号、一键复制。零依赖自带高亮器。
基础用法
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
vue
<script setup>
const code = `const answer = 42`
</script>
<template>
<SrCodeBlock :code="code" lang="ts" />
</template>为什么自带高亮器
代码高亮的常见方案是引入 Prism 或 highlight.js。本库选择自己实现,原因是:
| 方案 | 体积 | 覆盖语言 |
|---|---|---|
| highlight.js(全量) | 约 900 KB | 190+ |
| Prism(核心 + 常用) | 约 30 KB | 需按需引入 |
| 本库自带 | 约 3 KB | JS/TS/CSS/HTML/JSON/Shell 等常用 |
关键在于本库的实际用途:文档站与业务后台里的代码块, 95% 以上是 JS/TS/HTML/CSS/JSON。为这几种语言引入一个覆盖 190 种语言的库, 绝大部分体积是浪费。
自带高亮器的能力边界
它是基于正则的简单高亮,不是完整的语法分析器,因此:
- 极端写法(嵌套模板字符串、正则字面量内含引号)可能标错颜色
- 不支持冷门语言
能把 Token 分对类、颜色不出错——这是它要达成的目标。 需要像素级准确的高亮时,请换成专业库。
行号与复制
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
vue
<SrCodeBlock :code="code" lang="ts" line-numbers title="src/useCount.ts" />title 显示在头部左侧,复制按钮在右侧。标题在复制时不会被复制进去—— 它是元信息,不是代码的一部分。
const answer = 42copyable="false":不显示复制按钮
vue
<SrCodeBlock :code="code" :copyable="false" />复制失败的处理
复制走 navigator.clipboard,在非 HTTPS 环境下不可用。 组件会降级到 document.execCommand('copy'),若仍然失败则明确提示, 而不是静默失败。
为什么不用 execCommand 作为主方案
document.execCommand('copy') 已被标记为废弃,且在部分浏览器里 有同步阻塞的问题。navigator.clipboard 是异步的、更可靠, 只是要求安全上下文(HTTPS 或 localhost)。 两者结合才能覆盖开发环境与生产环境。
换行
默认不换行,超长代码横向滚动——这样行号与代码行的对应关系不会乱。
const veryLongVariableName = someFunction(argumentOne, argumentTwo, argumentThree, argumentFour)const veryLongVariableName = someFunction(argumentOne, argumentTwo, argumentThree, argumentFour)wrap:自动换行
vue
<SrCodeBlock :code="code" wrap />开启了 wrap 且同时开 line-numbers 时,行号会对不上换行后的视觉行—— 这是软换行的固有问题,无法完全避免。长代码建议保持不换行。
尺寸
const answer = 42const answer = 42const answer = 42vue
<SrCodeBlock size="sm" :code="code" lang="ts" />
<SrCodeBlock size="lg" :code="code" lang="ts" />支持的语言
lang 传入语言标识。未识别的语言按纯文本渲染,不会报错也不会乱标色。
| 标识 | 语言 |
|---|---|
js / javascript | JavaScript |
ts / typescript | TypeScript |
html / xml | HTML |
css / less / scss | 样式 |
json | JSON |
bash / sh / shell | Shell |
vue | Vue 单文件组件 |
vue
<SrCodeBlock :code="code" lang="ts" />
<SrCodeBlock :code="code" lang="python" /> <!-- 未识别,按纯文本渲染 -->Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
code | string | '' | 代码内容 |
lang | string | — | 语言标识;未识别时按纯文本渲染 |
lineNumbers | boolean | false | 是否显示行号 |
copyable | boolean | true | 是否显示复制按钮 |
title | string | — | 头部标题(如文件名) |
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸 |
wrap | boolean | false | 是否自动换行 |
无障碍
- 复制按钮带
aria-label="复制代码",复制成功后文案变为「已复制」 并带aria-live="polite"——否则读屏用户不知道操作是否成功 - 代码用
<pre><code>语义,读屏软件能识别为代码块并支持逐行朗读 - 行号是装饰性的,加
aria-hidden="true",避免朗读时把数字也念出来 - 长代码横向滚动时容器可键盘聚焦,否则键盘用户无法滚动查看