vue3前端实现一键复制,wangeditor富文本复制

发布于:2025-05-29 ⋅ 阅读:(48) ⋅ 点赞:(0)

首先需要拿到要复制的内容,然后调用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> -->
        <div
          class="text-content"
          v-html="formattedText"
          ref="textContainer"
       ></div>
    </div>
    <div v-if="editMode">
        <!-- <button @click="editMode = false">保存</button> -->
        <Editor
          ref="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-word
    tempDiv.querySelectorAll(".highlight-word").forEach((el) => {
      el.classList.remove("highlight-word");
      el.removeAttribute("data-word");
    });

    const cleanedHtml = tempDiv.innerHTML;

    // ✅ 使用 Clipboard API 复制处理后的 HTML
    await navigator.clipboard.write([
      new ClipboardItem({
        "text/html": new Blob([cleanedHtml], { type: "text/html" }),
      }),
    ]);
    ElMessage.success("内容已复制");
  } catch (err) {
    console.error("复制失败:", err);
    ElMessage.error("复制失败");
  }
};


网站公告

今日签到

点亮在社区的每一天
去签到