wangeditor富文本编辑器+vue3粘贴内容样式处理

又是一个风格和日立的上午,某只菜鸟高高兴兴的骑着小电驴去上班,本着上班只要不迟到的理念飞速前行(迟到扣钱啊~),高高兴兴的行走在路上。来到工位刚拴上我的绳子组长就开始滴滴俺,顿时我心中大感不妙,此时组长笑脸盈盈的走了过来说“今天有个任务交给你,至于是啥,你随我上电脑瞅瞅”。定睛一看,原来是富文本出了问题。废话不多说直接开始这个美丽的故事.......

        wangeditor富文本功能挺强大的。官网链接:优势 | wangEditor

        本文主要讲到粘贴文字这一块的处理,从浏览器上粘过来的文字一般都带有一些自己的样式,可能肉眼看到是黑色,其实是个灰色,主要修改粘贴后文字默认展示黑色。

一、粘贴函数介绍

customPaste用于处理粘贴的函数,官网有介绍。

<Editor
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :mode="mode"
      :style="{
        'height': props.height,
        'overflow-y': 'hidden',
        'width': `${100}%`
      }"
      @on-created="handleCreated"
      @on-change="onChange"
      @custom-paste="customPaste"

二、customPaste函数逻辑

// 自定义粘贴处理器
const customPaste = (editor: any, event: any) => {
  // 在preventDefault之前先获取内容
  const clipboardData = event.clipboardData;
  const html = clipboardData.getData('text/html');
  const text = clipboardData.getData('text/plain');
  event.preventDefault(); // 阻止默认粘贴行为
  // 如果有HTML内容,进行处理
  if (html) {
    console.log("开始处理HTML内容");
    // 创建临时DOM元素
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = html;

    // 遍历所有元素,移除 style.color 属性
    const elements = tempDiv.querySelectorAll('*');
    elements.forEach(el => {
      const element = el as HTMLElement;
      if (element.style.color) {
        element.style.removeProperty('color');
      }
      // 也可以考虑移除 background-color 如果需要
      // if (element.style.backgroundColor) {
      //   element.style.removeProperty('background-color');
      // }
    });

    // 获取清理后的 HTML 字符串
    const cleanHtml = tempDiv.innerHTML;

    // 将处理后的HTML插入编辑器
    editor.dangerouslyInsertHtml(cleanHtml);
  } else if (text) {
    // 处理纯文本内容
    // 插入纯文本,并可以设置默认样式
    editor.insertText(text);
  }
}

三、如果想加强一下效果

设置默认值,加强魔法

const editorConfig = {
  placeholder: "请输入内容...",
  MENU_CONF: {},
  readOnly: props.readOnly,
  // 设置默认文本颜色为黑色
  defaultStyle: {
    color: '#000000'
  }
};

四、完整代码

<script setup lang="ts">
import { uploadFile } from "@/utils/upload/upload.js";
import { onBeforeUnmount, ref, shallowRef, defineProps } from "vue";
import "@wangeditor/editor/dist/css/style.css";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { getObjVal, to } from "@iceywu/utils";
import { ElLoading } from "element-plus";

defineOptions({
  name: "PicUpload"
});
const props = defineProps({
  isOpen: {
    type: Boolean,
    default: true
  },
  height: {
    type: String,
    default: "500px"
  },
  readOnly: {
    type: Boolean,
    default: false
  }
});
const emit = defineEmits(["handleChange"]);

const valueHtml = defineModel<string>({
  default: ""
});

const mode = "default";
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef();

// 内容 HTML
// const valueHtml = ref(
//   "<p>仅提供代码参考,暂不可上传图片,可根据实际业务改写</p>"
// );
const toolbarConfig: any = { excludeKeys: "fullScreen" };
const editorConfig = {
  placeholder: "请输入内容...",
  MENU_CONF: {},
  readOnly: props.readOnly,
  // 设置默认文本颜色为黑色
  defaultStyle: {
    color: '#000000'
  }
};

// 更多详细配置看 https://www.wangeditor.com/v5/menu-config.html#%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87
editorConfig.MENU_CONF["uploadImage"] = {
  // 服务端上传地址,根据实际业务改写
  server: "",
  // form-data 的 fieldName,根据实际业务改写
  fieldName: "file",
  // 选择文件时的类型限制,根据实际业务改写
  allowedFileTypes: ["image/png", "image/jpg", "image/jpeg"],
  // 自定义上传
  async customUpload(file: File, insertFn: any) {
    const loading = ElLoading.service({ text: "上传中..." }) as any;
    const result = (
      await to(
        uploadFile(file, res => {
          const { percent, stage = "upload" } = res;
          loading.text = `上传中...${percent}%`;
        })
      )
    )[1] as any;
    console.log("🍭-----result-----", result);
    loading.close();
    // const { url, name } = result || {};
    const url = getObjVal(result, "data.url", "");
    const name = getObjVal(result, "data.fileName", "");
    console.log("🐬-----url, name-----", url, name);
    insertFn(url, name, url);
  }
};
editorConfig.MENU_CONF["uploadVideo"] = {
  // 服务端上传地址,根据实际业务改写
  server: "",
  // form-data 的 fieldName,根据实际业务改写
  fieldName: "file",
  // 选择文件时的类型限制,根据实际业务改写
  allowedFileTypes: ["video/*"],
  // 自定义上传
  async customUpload(file: File, insertFn: any) {
    const loading = ElLoading.service({ text: "上传中..." }) as any;
    const result = (
      await to(
        uploadFile(file, res => {
          const { percent, stage = "upload" } = res;
          loading.text = `上传中...${percent}%`;
        })
      )
    )[1] as any;
    console.log("🍭-----result-----", result);
    loading.close();
    // const { url, name } = result || {};
    const url = getObjVal(result, "data.url", "");
    const name = getObjVal(result, "data.fileName", "");
    console.log("🐬-----url, name-----", url, name);
    insertFn(url, name, url);
  }
};

const handleCreated = editor => {
  // 记录 editor 实例,重要!
  editorRef.value = editor;
};

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});
const onChange = (val: any) => {
  const valTemp = val.getHtml();
  emit("handleChange", valTemp);
};

// 自定义粘贴处理器
const customPaste = (editor: any, event: any) => {
  // 在preventDefault之前先获取内容
  const clipboardData = event.clipboardData;
  const html = clipboardData.getData('text/html');
  const text = clipboardData.getData('text/plain');
  event.preventDefault(); // 阻止默认粘贴行为
  // 如果有HTML内容,进行处理
  if (html) {
    console.log("开始处理HTML内容");
    // 创建临时DOM元素
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = html;

    // 遍历所有元素,移除 style.color 属性
    const elements = tempDiv.querySelectorAll('*');
    elements.forEach(el => {
      const element = el as HTMLElement;
      if (element.style.color) {
        element.style.removeProperty('color');
      }
      // 也可以考虑移除 background-color 如果需要
      // if (element.style.backgroundColor) {
      //   element.style.removeProperty('background-color');
      // }
    });

    // 获取清理后的 HTML 字符串
    const cleanHtml = tempDiv.innerHTML;

    // 将处理后的HTML插入编辑器
    editor.dangerouslyInsertHtml(cleanHtml);
  } else if (text) {
    // 处理纯文本内容
    // 插入纯文本,并可以设置默认样式
    editor.insertText(text);
  }
}
</script>

<template>
  <div class="wangeditor">
    <Toolbar
      v-if="props.isOpen"
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      :mode="mode"
      style="border-bottom: 1px solid #ccc"
    />
    <Editor
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :mode="mode"
      :style="{
        'height': props.height,
        'overflow-y': 'hidden',
        'width': `${100}%`
      }"
      @on-created="handleCreated"
      @on-change="onChange"
      @custom-paste="customPaste"
    />
  </div>
</template>

<style lang="scss" scoped>
.table_top {
  background-color: #fff;
}

:deep(.w-e-text-container) {
  .w-e-scroll {
    p {
      margin: 5px !important;
    }
  }
}
:deep(.w-e-text-placeholder) {
  left: 14px;
  top: 1px;
}
</style>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值