Skip to content

CodeBlock 代码块

代码高亮、行号、一键复制。零依赖自带高亮器

基础用法

ts
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 KB190+
Prism(核心 + 常用)约 30 KB需按需引入
本库自带约 3 KBJS/TS/CSS/HTML/JSON/Shell 等常用

关键在于本库的实际用途:文档站与业务后台里的代码块, 95% 以上是 JS/TS/HTML/CSS/JSON。为这几种语言引入一个覆盖 190 种语言的库, 绝大部分体积是浪费

自带高亮器的能力边界

它是基于正则的简单高亮,不是完整的语法分析器,因此:

  • 极端写法(嵌套模板字符串、正则字面量内含引号)可能标错颜色
  • 不支持冷门语言

能把 Token 分对类、颜色不出错——这是它要达成的目标。 需要像素级准确的高亮时,请换成专业库。

行号与复制

src/composables/useCount.tsts
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 显示在头部左侧,复制按钮在右侧。标题在复制时不会被复制进去—— 它是元信息,不是代码的一部分。

ts
const answer = 42

copyable="false":不显示复制按钮

vue
<SrCodeBlock :code="code" :copyable="false" />

复制失败的处理

复制走 navigator.clipboard在非 HTTPS 环境下不可用。 组件会降级到 document.execCommand('copy'),若仍然失败则明确提示, 而不是静默失败。

为什么不用 execCommand 作为主方案

document.execCommand('copy') 已被标记为废弃,且在部分浏览器里 有同步阻塞的问题。navigator.clipboard 是异步的、更可靠, 只是要求安全上下文(HTTPS 或 localhost)。 两者结合才能覆盖开发环境与生产环境。

换行

默认不换行,超长代码横向滚动——这样行号与代码行的对应关系不会乱

ts
const veryLongVariableName = someFunction(argumentOne, argumentTwo, argumentThree, argumentFour)
ts
const veryLongVariableName = someFunction(argumentOne, argumentTwo, argumentThree, argumentFour)

wrap:自动换行

vue
<SrCodeBlock :code="code" wrap />

开启了 wrap 且同时开 line-numbers 时,行号会对不上换行后的视觉行—— 这是软换行的固有问题,无法完全避免。长代码建议保持不换行。

尺寸

ts
const answer = 42
ts
const answer = 42
ts
const answer = 42
vue
<SrCodeBlock size="sm" :code="code" lang="ts" />
<SrCodeBlock size="lg" :code="code" lang="ts" />

支持的语言

lang 传入语言标识。未识别的语言按纯文本渲染,不会报错也不会乱标色。

标识语言
js / javascriptJavaScript
ts / typescriptTypeScript
html / xmlHTML
css / less / scss样式
jsonJSON
bash / sh / shellShell
vueVue 单文件组件
vue
<SrCodeBlock :code="code" lang="ts" />
<SrCodeBlock :code="code" lang="python" />  <!-- 未识别,按纯文本渲染 -->

Props

名称类型默认值说明
codestring''代码内容
langstring语言标识;未识别时按纯文本渲染
lineNumbersbooleanfalse是否显示行号
copyablebooleantrue是否显示复制按钮
titlestring头部标题(如文件名)
size'sm' | 'md' | 'lg''md'尺寸
wrapbooleanfalse是否自动换行

无障碍

  • 复制按钮带 aria-label="复制代码",复制成功后文案变为「已复制」 并带 aria-live="polite"——否则读屏用户不知道操作是否成功
  • 代码用 <pre><code> 语义,读屏软件能识别为代码块并支持逐行朗读
  • 行号是装饰性的,加 aria-hidden="true",避免朗读时把数字也念出来
  • 长代码横向滚动时容器可键盘聚焦,否则键盘用户无法滚动查看

自用组件库 · 源码分发 · 不发布 npm