关于在vue2中 使用wangeditor 的分析

265 阅读4分钟

第一步

先下载

    npm install @wangeditor/editor @wangeditor/editor-for-vue

然后在项目中创建一个组件 如 test.vue

 <template>
  <div>
    <div>
      <button @click="printEditorHtml">print html</button>
      <button @click="insertTextHandler">insert text</button>
      <button @click="disableHandler">disable</button>
    </div>
    <div
      class="editor-container"
      :class="{ fullscreen: isFullscreen }"
      style="border: 1px solid #ccc; margin-top: 10px"
    >
      <!-- 工具栏 -->
      <Toolbar
        style="border-bottom: 1px solid #ccc"
        :editor="editor"
        :defaultConfig="toolbarConfig"
      />
      <!-- 编辑器 -->
      <Editor
        style="height: 400px; overflow-y: hidden"
        :defaultConfig="editorConfig"
        v-model="html"
        @onChange="onChange"
        @onCreated="onCreated"
      />
    </div>
  </div>
</template>

<script>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";

export default {
  name: "MyEditor",
  components: { Editor, Toolbar },
  data() {
    return {
      editor: null,
      html: "<p>hello&nbsp;world</p>",
      isFullscreen: false, // 用于跟踪全屏状态
      toolbarConfig: {
        // toolbarKeys: [
        //   'bold', 'italic', 'underline', 'menu1', 'uploadImage', 'uploadVideo' // 添加自定义的 uploadWord 按钮
        // ]
      },
      editorConfig: {
        placeholder: "请输入内容...",
        // autoFocus: false,
        MENU_CONF: {
          uploadImage: {
            customUpload: (resultFiles, insertImgFn) => {
              const file = resultFiles[0];
              const allowedFileTypes = [
                "image/jpeg",
                "image/png",
                "image/gif",
                "image/jpg",
                "image/webp",
                "image/svg",
              ];
              const maxFileSize = 5 * 1024 * 1024; // 5MB

              // 检查文件类型
              if (!allowedFileTypes.includes(file.type)) {
                alert("文件类型不支持,请上传图片文件。");
                return;
              }

              // 检查文件大小
              if (file.size > maxFileSize) {
                alert("文件大小超出限制,请上传小于 5MB 的图片。");
                return;
              }

              const formData = new FormData();
              formData.append("file", file);
              queryOperator(formData)
                .then((response) => {
                  const url = response.data.url; // 根据你的接口返回结构调整
                  insertImgFn(url);
                })
                .catch((error) => {
                  console.error("图片上传失败", error);
                });
            },
            maxFileSize: 5 * 1024 * 1024, // 5MB
            maxNumberOfFiles: 5,
            allowedFileTypes: [
              "image/jpeg",
              "image/png",
              "image/gif",
              "image/jpg",
              "image/webp",
              "image/svg",
            ], //允许上传的格式
          },
          uploadVideo: {
            customUpload: (resultFiles, insertVideoFn) => {
              const file = resultFiles[0];
              const allowedFileTypes = [
                "video/mp4",
                "video/avi",
                "video/wmv",
                "video/flv",
                "video/rmvb",
              ];
              const maxFileSize = 10 * 1024 * 1024; // 10MB

              // 检查文件类型
              if (!allowedFileTypes.includes(file.type)) {
                alert("文件类型不支持,请上传视频文件。");
                return;
              }

              // 检查文件大小
              if (file.size > maxFileSize) {
                alert("文件大小超出限制,请上传小于 10MB 的视频。");
                return;
              }

              const formData = new FormData();
              formData.append("file", file);
              queryOperator(formData)
                .then((response) => {
                  const url = response.data.url; // 根据你的接口返回结构调整
                  insertVideoFn(url);
                })
                .catch((error) => {
                  console.error("视频上传失败", error);
                });
            },
            maxFileSize: 10 * 1024 * 1024, // 10MB
            allowedFileTypes: [
              "video/mp4",
              "video/avi",
              "video/wmv",
              "video/flv",
              "video/rmvb",
            ],
          },
        },
      },
    };
  },
  methods: {
    onCreated(editor) {
      this.editor = Object.seal(editor); // 【注意】一定要用 Object.seal() 否则会报错
      /*
     这是针对于 自定义的功能的
      
      let keysarr = ["menu1"]; //导入word的 自定义menu
      if (true) {
        keysarr.splice(1, 1, "btn1");  //预览的自定义button
      }
      // 注册自定义上传 Word 文件的处理逻辑
      this.toolbarConfig.insertKeys = {
        index: 32, // 插入的位置,基于当前的 toolbarKeys
        keys: keysarr,
      };
       // 监听自定义上传事件
      editor.on("upload-word-file", (file) => {
        this.uploadWordFile(file, editor);
      });
      // 监听自定义上传事件
      editor.on("btns", (bool) => {
        if (bool) console.log("object");
      });
      
      **/
      
      // 监听全屏事件
      editor.on("fullscreen", (isFullscreen) => {
        this.isFullscreen = isFullscreen;
      });
     
    },
    //自定义上传的function
    uploadWordFile(file, editor) {
      const allowedFileTypes = [
        "application/msword",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      ];
      const maxFileSize = 10 * 1024 * 1024; // 10MB
      // 检查文件类型
      if (!allowedFileTypes.includes(file.type)) {
        alert("文件类型不支持,请上传 Word 文件(.doc, .docx)。");
        return;
      }
      // 检查文件大小
      if (file.size > maxFileSize) {
        alert("文件大小超出限制,请上传小于 10MB 的 Word 文件。");
        return;
      }
      console.log(file);
      this.html = "<p>Ajax 异步设置内容 HTML-----文件删除</p>";
      const formData = new FormData();
      formData.append("qqfile", file);
      // 自定义上传逻辑
    },
    onChange(editor) {
      console.log("onChange", editor.getHtml()); // onChange 时获取编辑器最新内容
    },
    insertTextHandler() {
      const editor = this.editor;
      if (editor == null) return;
      editor.insertText(" hello ");
    },
    printEditorHtml() {
      const editor = this.editor;
      if (editor == null) return;
      console.log(editor.getHtml());
    },
    disableHandler() {
      const editor = this.editor;
      if (editor == null) return;
      editor.disable();
    },
  },
  beforeDestroy() {
    const editor = this.editor;
    if (editor == null) return;
    editor.destroy(); // 组件销毁时,及时销毁 editor ,重要!!!
  },
  mounted() {
    // 模拟 ajax 请求,异步渲染编辑器
    // setTimeout(() => {
    //   this.html = "<p>Ajax 异步设置内容 HTML</p>";
    // }, 1500);
  },
};
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>
<style scoped>
/* 全屏时的样式 */
.fullscreen ~ .other-elements {
  display: none;
}

.editor-container.fullscreen {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  background: #fff;
}
</style>


第二步 (如果需要自定义一些功能) 在 utils文件夹 或者其他文件夹 创建 (自定义)coustomizer.js 和 setupWangEditor.js

coustomizer.js


export class MyModalMenu {
    constructor() {
        this.title = '导入Word'
        this.tag = 'button'
        this.showModal = true
        this.modalWidth = 400
    }
    isActive(editor) {
        return false
    }
    getValue(editor) {
        return ''
    }
    isDisabled(editor) {
        return false
    }
    exec(editor, value) { }
    getModalPositionNode(editor) {
        return null
    }
    getModalContentElem(editor) {
        const content = document.createElement('div')
        content.innerHTML = `
            <div style="padding: 20px;">
                <h3>导入Word文件</h3>
                <input id="wordFileInput" type="file" accept=".doc, .docx" style="margin-bottom: 10px;" />
                <div style="text-align: right;">
                    <button id="uploadBtn" class="el-button el-button--primary" style="margin-right: 10px;">确认导入</button>
                    <button id="cancelBtn" class="el-button">取消</button>
                </div>
            </div>
        `
        const uploadBtn = content.querySelector('#uploadBtn')
        const cancelBtn = content.querySelector('#cancelBtn')
        uploadBtn.onclick = () => {
            const input = content.querySelector('#wordFileInput')
            const file = input.files[0]
            if (file) {
                editor.emit('upload-word-file', file)
                editor.hidePanelOrModal() // 关闭对话框
            } else {
                alert('请选择一个Word文件')
            }
        }
        cancelBtn.onclick = () => {
            editor.hidePanelOrModal() // 关闭对话框
        }
        return content
    }
}

export class MyButtonMenu {
    constructor() {
        this.title = '预览' // 自定义菜单标题
        // this.iconSvg = '<svg>...</svg>' // 可选
        this.tag = 'button'
    }
    // 获取菜单执行时的 value ,用不到则返回空 字符串或 false
    getValue(editor) {
        return ' hello '
    }
    // 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
    isActive(editor) {
        return false
    }
    // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
    isDisabled(editor) {
        return false
    }
    // 点击菜单时触发的函数
    exec(editor, value) {
        if (this.isDisabled(editor)) return
        editor.emit('btns', true)
        // editor.insertText(value) // value 即 this.value(editor) 的返回值
    }
}



setupWangEditor.js 


import { Boot } from '@wangeditor/editor'
import { MyModalMenu,MyButtonMenu } from "./zdy"

export function setupWangEditor() {
  const menu1Conf = {
    key: 'menu1', // 定义 menu key :要保证唯一、不重复(重要)
    factory() {
      return new MyModalMenu() // 使用自定义的菜单类
    },
  }
  const btn1Conf = {
    key: 'btn1', // 定义 menu key :要保证唯一、不重复(重要)
    factory() {
      return new MyButtonMenu() // 使用自定义的菜单类
    },
  }

  const module = {
    menus: [menu1Conf,btn1Conf],
  }

  Boot.registerModule(module)
}


然后在 main.js 里导入

import { setupWangEditor } from './utils/setupWangEditor' // 确保路径正确
// 设置 WangEditor
setupWangEditor();