基于 highlight.js 的代码块组件封装
2025/7/29大约 3 分钟
基于 highlight.js 的代码块组件封装
代码块组件主要用于显示 Vagrantfile 模版,而 Vagrantfile 中的实际内容其实是 Ruby 脚本。使用 highlight.js 对模版内容进行高亮展示能够提供更好的用户体验。另外还需要拷贝模版和下载模版的需求。
安装依赖和配置
安装 highlight.js 和 @highlightjs/vue-plugin
yarn add highlight.js @highlightjs/vue-plugin注册插件的方式有两种:
第一种,全局注册——在 main.ts 文件中导入相关依赖,调用 app.use() 接口来注册插件
import 'highlight.js/styles/github-dark.css'
import 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'
const app = createApp(App)
app.use(router)
app.use(hljsVuePlugin)
app.mount('#app')第二种,局部注册——在 CodeBlock.vue 文件(手动创建)中导入相关依赖,手动获取组件
<template>
<!-->省略的模版内容<-->
<highlightjs
:language="language"
:code="code"
class="rounded-xl bg-gray-800 text-sm text-white p-4"
/>
</template>
<script setup lang="ts">
import 'highlight.js/styles/github-dark.css'
import 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'
const highlightjs = hljsVuePlugin.component;
// 其他功能代码
</script>实际使用视具体情况而定,全局注册比较简单,注册之后项目中任何需要展示代码的地方都可一使用 highlightjs 这个组件;局部注册仅在 CodeBlock.vue 文件中可用,如果其他地方没有代码展示需要,仅在 CodeBlock.vue 文件内使用会更好。不建议两种方式同时存在。
代码高亮组件封装
组成 UI 的元素仅两个按钮和一个 highlightjs 组件,样式采用 TailwindCSS,图标则由 Lucide 提供,具体可以查看这篇内容。代码大致如下:
<template>
<div class="relative group">
<div
class="absolute top-5 right-5 flex gap-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity"
>
<button
class="p-2 bg-gray-700 hover:bg-gray-600 rounded text-white"
@click="copyCode"
:title="copied ? 'Copied!' : 'Copy code'"
>
<component :is="copied ? Check : ClipboardCopy" class="w-4 h-4" />
</button>
<button
class="p-2 bg-gray-700 hover:bg-gray-600 rounded text-white"
@click="downloadCode"
title="Download code"
>
<Download class="w-4 h-4" />
</button>
</div>
<highlightjs
:language="language"
:code="code"
class="rounded-xl bg-gray-800 text-sm text-white p-4"
/>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import { ClipboardCopy, Check, Download } from 'lucide-vue-next'
import 'highlight.js/styles/github-dark.css'
import 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'
const highlightjs = hljsVuePlugin.component;
const props = defineProps({
code: { type: String, required: true },
language: { type: String, default: 'javascript' },
filename: { type: String, default: '' },
})
</script>这里组件注册使用的是局部注册的方式。基础外观完成了,下面就是主要交互功能了。
代码拷贝与下载实现
具体的代码其实并不需要自己去写,只需要告诉 AI 需求,就能够完成我想要的功能。
<script setup lang="ts">
// 省略的内容
const copied = ref(false)
const copyCode = async () => {
try {
await navigator.clipboard.writeText(props.code)
copied.value = true
setTimeout(() => (copied.value = false), 1500)
} catch (err) {
console.error('Copy failed:', err)
}
}
const downloadCode = () => {
const blob = new Blob([props.code], { type: 'text/plain;charset=utf-8' })
const extensionMap: { [key: string]: string } = {
ruby: 'rb',
cpp: 'cpp',
python: 'py',
bash: 'sh',
}
const ext = extensionMap[props.language] || 'txt'
const filename = props.filename || `code.${ext}`
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = filename
link.click()
URL.revokeObjectURL(link.href)
}
</script>完整代码参考这里
实现效果
编辑 AboutView.vue 内容如下:
<template>
<div class="about flex flex-col justify-center py-8">
<CodeBlock :code="code" language="ruby" filename="Vagrantfile" />
</div>
</template>
<script setup lang="ts">
import CodeBlock from '@/components/CodeBlock.vue'
const code =
'Vagrant.configure("2") do |config|\n' +
' config.vm.box = "ubuntu-focal-qt"\n' +
' config.vm.box_url = "http://192.168.5.114:9321/api/ubuntu-focal-desktop-en-qt"\n' +
'\n' +
' config.vm.provider "virtualbox" do |vb|\n' +
' vb.gui = true\n' +
' vb.cpus = 4\n' +
' vb.memory = "2048"\n' +
' end\n' +
'\n' +
' config.vm.provision "shell", inline: <<-SHELL\n' +
' apt-get update\n' +
' SHELL\n' +
'end'
</script>
