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