前言
在vscode中,有代码高亮的功能。那么如果在前端项目中,展示代码时如何实现高亮效果。
这是我们可以使用highlight.js
,highlight.js
是一款基于JavaScript的语法高亮库,它具有以下功能:
备注:关于复制的方法execCommand已经废弃了,我懒得改了,替代方式见:前端复制、剪切、禁止复制等
使用
安装
## 这个是highlight.js基础依赖
npm install --save highlight.js
## 安装支持vue3 的@highlightjs/vue-plugin 依赖
npm install --save @highlightjs/vue-plugin
main.js引入
// highlight 的样式,依赖包,组件
import 'highlight.js/styles/atom-one-dark.css'
import 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'
//注册组件
app.use(hljsVuePlugin)
使用
<template>
<div>
<highlightjs language="JavaScript" :autodetect="false" :code="code"></highlightjs>
</div>
</template>
<script setup lang="ts">
let code = 'import { createApp } from "vue";import App from "./App.vue";'
</script>
<style scoped lang="scss">
</style>
注意:
- 因为插件不支持响应式数据,所以不要使用ref定义响应式变量
- autodetect 将自动匹配设置为false,自动匹配一般不准
比较常用的语言有:HTML
、XML
、C++
、CSS
、Java
、JavaScript
、PHP
、Python
、SCSS
、SQL
、TypeScript
其他语言可以自行查看官方文档
效果
修改样式
更换主题
现在我们使用的主题是:
import 'highlight.js/styles/atom-one-dark.css'
可以根据官方demo,找到一个自己喜欢的主题。然后引入就好,如何引用呢?找到highlight.js/styles
文件夹,引入对应的样式即可,我这里用的这个androidstudio
,感觉不错
扫描二维码关注公众号,回复:
14349005 查看本文章
import 'highlight.js/styles/androidstudio.css'
自定义样式
到目前为止,还是不太好看,我想要的是这样的
这里可以自己写一些样式来实现
<template>
<div class="hljs-container" codetype="JavaScript">
<highlightjs language="JavaScript" :autodetect="false" :code="code"></highlightjs>
</div>
</template>
<script setup lang="ts">
let code = `let a = 1;import hljs-containerVuePlugin from '@highlightjs/vue-plugin';import hljs-containerVuePlugin from '@highlightjs/vue-plugin';
import hljs-containerVuePlugin from '@highlightjs/vue-plugin';
import hljs-containerVuePlugin from '@highlightjs/vue-plugin';`;
</script>
<style scoped lang="scss">
/* 语法高亮 */
.hljs-container {
position: relative;
display: block;
width: 600px;
padding: 30px 5px 2px;
overflow-x: hidden;
line-height: 20px;
text-align: left;
background: #21252b;
box-shadow: 0 10px 30px 0 rgb(0 0 0 / 40%);
}
/** 3个点 */
.hljs-container::before {
position: absolute;
top: 10px;
left: 15px;
width: 12px;
height: 12px;
overflow: visible;
font-weight: 700;
font-size: 16px;
line-height: 12px;
white-space: nowrap;
text-indent: 75px;
background-color: #fc625d;
border-radius: 16px;
box-shadow: 20px 0 #fdbc40, 40px 0 #35cd4b;
content: attr(codetype);
}
/** 滚动条 */
:deep(.hljs) {
overflow-x: auto;
}
:deep(.hljs::-webkit-scrollbar) {
width: 12px !important;
height: 12px !important;
}
:deep(.hljs::-webkit-scrollbar-thumb) {
height: 30px !important;
background: #d1d8e6;
background-clip: content-box;
border: 2px solid transparent;
border-radius: 19px;
opacity: 0.8;
}
:deep(.hljs::-webkit-scrollbar-thumb:hover) {
background: #a5b3cf;
background-clip: content-box;
border: 2px solid transparent;
}
:deep(.hljs::-webkit-scrollbar-track-piece) {
width: 30px;
height: 30px;
background: #333;
}
::-webkit-scrollbar-button {
display: none;
}
</style>
功能
需要添加 代码行数 和 点击复制的功能
效果
完整代码
组件
<template>
<div class="hljs-container" codetype="JavaScript" v-code>
<highlightjs language="JavaScript" :autodetect="false" :code="code"></highlightjs>
</div>
</template>
<script setup lang="ts">
import vCode from './line';
let code = `let a = 1;
import hljs-containerVuePlugin from '@highlightjs/vue-plugin';
import hljs-containerVuePlugin from '@highlightjs/vue-plugin';
<div class="hljs-container" codetype="JavaScript" v-code>
<highlightjs language="JavaScript" :autodetect="false" :code="code"></highlightjs>
</div>`;
</script>
<style scoped lang="scss">
@import "./code.scss";
</style>
指令
import './code.scss';
const vCode = {
mounted(el: any) {
//获取代码片段
let code = el.querySelector('code.hljs')
let pre = document.getElementsByTagName('pre')[0]
let html = code?.innerHTML
let size = html.split('\n').length
//插入行数
let ul = document.createElement('ul')
for (let i = 1; i <= size; i++) {
let li = document.createElement('li')
li.innerText = i + ''
ul.appendChild(li)
}
ul.classList.add('hljs-code-number')
el.insertBefore(ul, pre)
//插入复制功能
let copy = document.createElement('div')
copy.classList.add('hljs-copy')
copy.innerText = '复制'
//添加点击事件
copy.addEventListener('click', () => {
//创建一个输入框
let textarea = document.createElement('textarea')
document.body.appendChild(textarea);
textarea.setAttribute('readonly', 'readonly')
textarea.value = code.innerText;
textarea.select();
if (document.execCommand('copy')) {
document.execCommand('copy');
copy.innerText = '复制成功'
}
document.body.removeChild(textarea);
})
pre.appendChild(copy)
//鼠标移入显示复制按钮
el.addEventListener('mouseout', () => {
copy.innerText = '复制'
copy.style.display = "none"
})
el.addEventListener('mouseover', () => {
copy.style.display = "block"
})
}
}
export default vCode
样式
/* 语法高亮 */
.hljs-container {
position: relative;
display: block;
display: flex;
width: max-content;
margin-left: 100px;
padding: 30px 10px 2px 0;
overflow-x: hidden;
font-size: 14px;
line-height: 24px;
text-align: left;
background: #21252b;
box-shadow: 0 10px 30px 0 rgb(0 0 0 / 40%);
}
/** 3个点 */
.hljs-container::before {
position: absolute;
top: 10px;
left: 15px;
width: 12px;
height: 12px;
overflow: visible;
font-weight: 700;
font-size: 16px;
line-height: 12px;
white-space: nowrap;
text-indent: 75px;
background-color: #fc625d;
border-radius: 16px;
box-shadow: 20px 0 #fdbc40, 40px 0 #35cd4b;
content: attr(codetype);
}
/** 滚动条 */
:deep(.hljs) {
overflow-x: auto;
}
:deep(.hljs::-webkit-scrollbar) {
width: 12px !important;
height: 12px !important;
}
:deep(.hljs::-webkit-scrollbar-thumb) {
height: 30px !important;
background: #d1d8e6;
background-clip: content-box;
border: 2px solid transparent;
border-radius: 19px;
opacity: 0.8;
}
:deep(.hljs::-webkit-scrollbar-thumb:hover) {
background: #a5b3cf;
background-clip: content-box;
border: 2px solid transparent;
}
:deep(.hljs::-webkit-scrollbar-track-piece) {
width: 30px;
height: 30px;
background: #333;
}
::-webkit-scrollbar-button {
display: none;
}
/** 行数样式 */
.hljs-code-number {
padding: 17px 10px 0;
color: #d1d8e6;
font-size: 12px;
list-style: none;
border-right: 1px solid #d1d8e6;
}
/** 复制样式 */
.hljs-copy {
position: absolute;
top: 50px;
right: 30px;
display: none;
padding: 0 10px;
color: #66a9ff;
font-size: 10px;
background-color: #ecf5ff;
border-radius: 3px;
cursor: pointer;
}