vue3前端实现一键复制,wangeditor富文本复制
首先需要拿到要复制的内容,然后调用https的navigator.clipboard方法进行复制,但是这个因为浏览器策略只能在本地localhost和https环境下才能生效,http环境访问不到这个方法,在http环境在可以使用传统方式创建 textarea 进行复制
下面展示我在项目中用到的两种情况下的复制代码:
①复制的内容格式比较复杂,外面的大盒子里展示内容有很多逻辑判断,不方便直接获取到盒子里的内容,这个时候复制的内容需要手动用模板字符串进行拼接
// 获取到要复制的内容,带格式
const copyQuestions = () => {const selected = localQuestions.value.filter((item) => item.isSelected);if (selected.length === 0) return;const text = selected.map((item, idx) => {const topic = item.topic;const options = Object.entries(topic.option).map(([key, val], i) => `选项${String.fromCharCode(65 + i)}:\t${val}`).join("\n");return (`题目${getCircleNumber(idx + 1)}:${questionType[item.topicType]}\n` +`题目内容:\t${topic.question}\n` +options +"\n" +`正确答案:\t${topic.answer}\n` +`答案解析:\t${topic.desc}\n`);}).join("\n");copyToClipboard(text);
};//复制方法
const copyToClipboard = async (text) => {try {if (navigator.clipboard && window.isSecureContext) {// 优先使用现代方式(仅在 HTTPS 或 localhost 下有效)await navigator.clipboard.writeText(text);} else {// 非 HTTPS 环境,使用传统方式创建 textarea 进行复制console.log("非 HTTPS 环境,使用传统方式创建 textarea 进行复制");const textarea = document.createElement("textarea");textarea.value = text;textarea.style.position = "fixed"; // 防止滚动到页面底部textarea.style.opacity = "0";document.body.appendChild(textarea);textarea.focus();textarea.select();const successful = document.execCommand("copy");document.body.removeChild(textarea);if (!successful) {throw new Error("execCommand 复制失败");}}ElMessage.success("复制成功");} catch (err) {console.error("复制失败:", err);ElMessage.error("复制失败,请手动复制");}
};
② 有编辑和非编辑模式,两种模式都支持一键复制,编辑模式用的是@wangeditor/editor-for-vue,5.1.12版本的,复制代码如下
template代码
<template><div v-if="!editMode"><!-- <button @click="editMode = true">编辑</button> --><divclass="text-content"v-html="formattedText"ref="textContainer"></div></div><div v-if="editMode"><!-- <button @click="editMode = false">保存</button> --><Editorref="editorContainer"class="editor_box"style="height: max-content; overflow-y: hidden"v-model="valueHtml":defaultConfig="editorConfig"mode="default"@onCreated="handleCreated"@onChange="handleEditorChange"/></div></template>
script中的代码示例
const textContainer = ref<HTMLElement | null>(null);const handleCreated = (editor: any) => {editorRef.value = editor; // 记录 editor 实例,重要!
};// 富文本复制(去除高亮样式)
const copyFormattedContent = async () => {try {let html = "";if (props.editMode) {if (!editorRef.value || typeof editorRef.value.getHtml !== "function") {ElMessage.info("编辑器未初始化或类型错误");return;}html = editorRef.value.getHtml();} else {const textToCopy = textContainer.value;if (!textToCopy) {ElMessage.info("复制区域未找到");return;}html = textToCopy.innerHTML;}// ✅ 创建 DOM,清除高亮样式const tempDiv = document.createElement("div");tempDiv.innerHTML = html;// ✅ 清除高亮样式tempDiv.querySelectorAll("span, strong").forEach((el: any) => {const hasBgColor =el.style.backgroundColor ||el.getAttribute("style")?.includes("background");if (hasBgColor) {el.removeAttribute("style");}});// ✅ 移除高亮 class 和 data-wordtempDiv.querySelectorAll(".highlight-word").forEach((el) => {el.classList.remove("highlight-word");el.removeAttribute("data-word");});const cleanedHtml = tempDiv.innerHTML;// ✅ 使用 Clipboard API 复制处理后的 HTMLawait navigator.clipboard.write([new ClipboardItem({"text/html": new Blob([cleanedHtml], { type: "text/html" }),}),]);ElMessage.success("内容已复制");} catch (err) {console.error("复制失败:", err);ElMessage.error("复制失败");}
};