Vue2和Vue3使用highlight.js进行代码高亮,Clipboard进行代码复制有一定差异,主要是this在vue3中不指向组件实例。
假设内容区域代码:
<article class="article-content" :title="article.title" id="article-content" v-html="article.content"></article>
页面的内是通过v-html渲染而来。
首先是安装这两个插件:
npm i clipboard npm i highlight.js
然后是引入,不需要全站引入,则在需要使用的页面引入:
//DetailView.vue 会展示代码的页面 import hljs from "highlight.js"; import "highlight.js/styles/github-dark-dimmed.min.css"; // 选择你喜欢的主题样式 import ClipboardJS from "clipboard";
后续需要分Vue2和Vue3版本分别处理:
// Vue2
async mounted () {
// 代码高亮
await this.highlightCode();
// 初始化 Clipboard.js
await this.initClipboard();
// 监听内容变化
this.$watch(
() => this.article.content, //article.content 是内容
() => {
this.$nextTick(() => {
this.initClipboard();
});
}
);
},
methods:{
//高亮代码
highlightCode() {
hljs.configure({
cssSelector: "pre", //修改默认的代码选择器
});
const blocks = document.querySelectorAll(".article-content pre");
blocks.forEach((block) => {
hljs.highlightElement(block);
// 创建复制按钮
const copyBtn = document.createElement("button");
copyBtn.type = "button";
copyBtn.className = "copy-btn";
copyBtn.innerText = "copy";
// 将按钮插入到 pre 标签内部
block.appendChild(copyBtn);
});
},
// 初始化剪切板
initClipboard() {
// 销毁之前的实例
if (this.clipboard) {
this.clipboard.destroy();
}
// 初始化 Clipboard.js
this.clipboard = new ClipboardJS(".copy-btn", {
text: function(trigger) {
// 找到对应的 pre 标签
const preElement = trigger.parentElement;
// 克隆 pre 标签
const codeText = preElement.cloneNode(true);
// 移除 pre 标签内的所有 .copy-btn 元素
codeText.querySelectorAll(".copy-btn").forEach((btn) => btn.remove());
// 返回克隆后的内容的文本
return codeText.innerText;
},
});
// 处理复制成功事件
this.clipboard.on("success", (e) => {
//console.log("Text copied to clipboard:", e.text);
// alert("代码已复制到剪贴板");
});
// 处理复制失败事件
this.clipboard.on("error", (e) => {
console.error("Failed to copy text: ", e);
alert("复制失败,请手动复制");
});
}
}//vue3
import { ref, onMounted, watch, nextTick } from 'vue'
// 声明 clipboard 实例的响应式变量
const clipboard = ref(null)
//监控文章内容变化
watch(
() => article.value.content,
() => {
nextTick(() => {
initClipboard();
});
}
);
onMounted(async () => {
// 代码高亮
await highlightCode();
// 初始化 Clipboard.js
await initClipboard();
});
//高亮代码
function highlightCode() {
//由于highlight.js 默认的代码识别是 <pre><code>...</code></pre>
//这里根据实际情况<pre>...</pre> 修改
hljs.configure({
cssSelector: "pre",
});
//一篇文章内的多个代码区域
const blocks = document.querySelectorAll(".article-content pre");
blocks.forEach((block) => {
// 对每个代码区域启用代码高亮
hljs.highlightElement(block);
// 创建复制按钮
const copyBtn = document.createElement("button");
copyBtn.type = "button";
copyBtn.className = "copy-btn";
copyBtn.innerText = "copy";
// 将按钮插入到 pre 标签内部(尾部)
block.appendChild(copyBtn);
});
}
// 初始化剪切板
function initClipboard() {
// 销毁之前的实例
if (clipboard.value) {
clipboard.value.destroy();
}
// 初始化 Clipboard.js
clipboard.value = new ClipboardJS(".copy-btn", {
text: function(trigger) {
// 找到对应的 pre 标签
const preElement = trigger.parentElement;
// 克隆 pre 标签
const codeText = preElement.cloneNode(true);
// 移除 pre 标签内的所有 .copy-btn 元素
codeText.querySelectorAll(".copy-btn").forEach((btn) => btn.remove());
// 返回克隆后的内容的文本
return codeText.innerText;
},
});
// 处理复制成功事件
clipboard.value.on("success", (e) => {
//console.log("Text copied to clipboard:", e.text);
// alert("代码已复制到剪贴板");
});
// 处理复制失败事件
clipboard.value.on("error", (e) => {
console.error("Failed to copy text: ", e);
alert("复制失败,请手动复制");
});
}这样在代码区域右上角有一个复制按钮,点击复制之后,如果成功则系统剪贴板内有复制的内容,如果复制失败会弹窗和在浏览器控制台报错。而且,复制按钮本身的文字不会被复制。




