vue项目中使用WangEditor编辑器,在火狐浏览器Firefox中输入中文报错问题

14 阅读2分钟

之前开发项目中涉及到富文本编辑器都是使用的WangEditor,但是这次甲方试用过程中反馈出现以下情况:

live.csdn.net/v/509328

原本的代码如下,核查使用的是火狐浏览器

<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,所以编辑器仍显示空内容或旧内容。

需要:

  1. 在 props.modelValue 变化时,调用 editorRef.value.setHtml(newValue)
  2. 础保只在编辑器已创建后才调用(避免 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>

这样就可以实现了编辑表单中的内容回显