之前开发项目中涉及到富文本编辑器都是使用的WangEditor,但是这次甲方试用过程中反馈出现以下情况:
原本的代码如下,核查使用的是火狐浏览器
<el-form-item label="任务描述:" prop="ms">
<wang-editor v-model="ruleForm.ms" placeholder="请输入任务描述"></wang-editor>
</el-form-item>
import WangEditor from "@/components/editor/WangEditor";
components: { WangEditor },
官方给出回复建议尝试使用 wangeditor-next
编辑
1、下载 wangeditor-next :命令npm install @wangeditor-next/editor @wangeditor-next/editor-for-vue
2、封装一个富文本编辑器组件WangEditorNext:
<div style="border: 1px solid #ccc">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 300px; overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="handleCreated"
/>
</div>
</template>
<script>
import "@wangeditor-next/editor/dist/css/style.css";
import { onBeforeUnmount, ref, shallowRef, watch } from "vue";
import { Editor, Toolbar } from "@wangeditor-next/editor-for-vue";
import config from "@/config/upload";
import { ElMessage } from "element-plus";
import { ElLoading } from "element-plus";
export default {
components: { Editor, Toolbar },
props: {
modelValue: {
type: String,
default: "",
},
placeholder: {
type: String,
default: "请输入内容...",
},
},
setup(props, { emit }) {
const editorRef = shallowRef();
const valueHtml = ref("");
const toolbarConfig = {};
const editorConfig = { placeholder: props.placeholder };
editorConfig.MENU_CONF = {};
editorConfig.MENU_CONF.uploadImage = {
maxFileSize: 2 * 1024 * 1024,
customUpload(file, insertFn) {
const maxSize = file.size / 1024 / 1024 < config.maxSize;
if (!maxSize) {
ElMessage({
message: `上传文件大小不能超过 ${config.maxSize}MB!`,
type: "warning",
});
return false;
}
const obj = new FormData();
obj.append("file", file);
var apiObj = config.apiObj;
const loading = ElLoading.service({
lock: true,
text: "图片上传中...",
background: "rgba(0, 0, 0, 0.7)",
});
apiObj
.upload(obj)
.then((res) => {
insertFn(res, "", res);
loading.close();
})
.catch((err) => {
loading.close();
console.log(err);
});
},
};
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
watch(valueHtml, (newValue) => {
emit("update:modelValue", newValue);
});
watch(
() => props.modelValue,
(newValue) => {
valueHtml.value = newValue;
}
);
const handleCreated = (editor) => {
editorRef.value = editor;
};
return {
editorRef,
valueHtml,
mode: "default",
toolbarConfig,
editorConfig,
handleCreated,
};
},
};
</script>
3、修改父组件中的引入:
<el-form-item label="任务描述:" prop="ms">
<wang-editor-next v-model="ruleForm.ms" placeholder="请输入任务描述"></wang-editor-next>
</el-form-item>
import WangEditorNext from "@/components/editor/WangEditorNext";
components: { WangEditorNext },
这样修改后重新在火狐浏览器中尝试,可以正常输入文字了。但是接下来进行编辑时,发现不会回显已有数据,富文本编辑器中为空。原因是在 watch(props.modelValue) 中只是改了 valueHtml.value,但没有通知编辑器实例去加载新 HTML,所以编辑器仍显示空内容或旧内容。
需要:
- 在
props.modelValue变化时,调用editorRef.value.setHtml(newValue) - 础保只在编辑器已创建后才调用(避免
editorRef.value为 null)
修改后的组件代码:
<template>
<div style="border: 1px solid #ccc">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 300px; overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="handleCreated"
/>
</div>
</template>
<script>
import "@wangeditor-next/editor/dist/css/style.css";
import { onBeforeUnmount, ref, shallowRef, watch } from "vue";
import { Editor, Toolbar } from "@wangeditor-next/editor-for-vue";
import config from "@/config/upload";
import { ElMessage } from "element-plus";
import { ElLoading } from "element-plus";
export default {
components: { Editor, Toolbar },
props: {
modelValue: {
type: String,
default: "",
},
placeholder: {
type: String,
default: "请输入内容...",
},
},
setup(props, { emit }) {
const editorRef = shallowRef();
const valueHtml = ref("");
const toolbarConfig = {};
const editorConfig = { placeholder: props.placeholder };
editorConfig.MENU_CONF = {};
editorConfig.MENU_CONF.uploadImage = {
maxFileSize: 2 * 1024 * 1024,
customUpload(file, insertFn) {
const maxSize = file.size / 1024 / 1024 < config.maxSize;
if (!maxSize) {
ElMessage({
message: `上传文件大小不能超过 ${config.maxSize}MB!`,
type: "warning",
});
return false;
}
const obj = new FormData();
obj.append("file", file);
var apiObj = config.apiObj;
const loading = ElLoading.service({
lock: true,
text: "图片上传中...",
background: "rgba(0, 0, 0, 0.7)",
});
apiObj
.upload(obj)
.then((res) => {
insertFn(res); // ✅ 通常只需传 URL,不需要 alt/href
loading.close();
})
.catch((err) => {
loading.close();
console.log(err);
});
},
};
// 同步外部 modelValue 到编辑器
const syncModelToEditor = (html) => {
if (editorRef.value && html !== editorRef.value.getHtml()) {
editorRef.value.setHtml(html || ""); // ⭐ 关键:主动设置内容
}
};
onBeforeUnmount(() => {
editorRef.value?.destroy();
});
// 监听外部传入的 modelValue 变化
watch(
() => props.modelValue,
(newVal) => {
valueHtml.value = newVal || ""; // 更新内部响应式变量
syncModelToEditor(newVal); // ⭐ 主动同步到编辑器
},
{ immediate: true } // ⭐ 立即执行一次,确保初始化时加载内容
);
// 监听内部编辑器内容变化,emit 出去
watch(valueHtml, (newVal) => {
emit("update:modelValue", newVal);
});
const handleCreated = (editor) => {
editorRef.value = editor;
// 编辑器创建后,立即设置初始内容(双重保险)
syncModelToEditor(props.modelValue);
// 监听编辑器内容变化
editor.on("change", () => {
const html = editor.getHtml();
valueHtml.value = html; // 触发 emit
});
};
return {
editorRef,
valueHtml,
mode: "default",
toolbarConfig,
editorConfig,
handleCreated,
};
},
};
</script>
这样就可以实现了编辑表单中的内容回显