vue 使用wangeditor 富文本编辑框 (编写,返显)

1. npm install --save @wangeditor/editor-for-vue

2. npm install js-base64

3.npm install @wangeditor/editor

<template>
    <div>
      <Toolbar
          :editor="editor"
          :defaultConfig="toolbarConfig"
          :mode="mode"
      />
      <Editor
          v-model="editors"
          :defaultConfig="editorConfig"
          :mode="mode"
          style="height: 400px"
          @onCreated="onCreated"
      />
      <button @click="submit">点击提交</button>
      <button @click="show">展示功能</button>
      <div class="show">
        <Editor
            v-model="editors"
            :defaultConfig="editorConfig"
            :mode="mode"
            style="height: 400px"
            @onCreated="onCreated"
        />
        <div v-html="content"></div>
      </div>
    </div>
</template>
<script>
import { Base64 } from 'js-base64'
import { Loading, Message } from 'element-ui'
import { DomEditor } from "@wangeditor/editor";
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
export default {
components: { Editor, Toolbar },
data() {
  let loading = ''
    return {
      editor: null,
      editors:'',
      content: "",
      toolbarConfig: {
        toolbarKeys: [
          // 一些常用的菜单 key
          "headerSelect", // 标题
          // "header1", // 标题1
          // "header2", // 标题2
          // "header3", // 标题3
          // "header4", // 标题4
          // "header5", // 标题5
          "bold", // 粗体
          "underline", // 下划线
          "italic", // 斜体
          "through", // 删除线
          "code", // 行内代码
          "sub", // 下标
          "sup", // 上标
          "clearStyle", // 清除格式
          "color", // 字体颜色
          "bgColor", // 背景色
          "fontSize", // 字号
          "fontFamily", // 字体
          "indent", // 增加缩进
          "delIndent", // 减少缩进
          "justifyLeft", // 左对齐
          "justifyRight", // 右对齐
          "justifyCenter", // 居中对齐
          "justifyJustify", // 两端对齐
          "lineHeight", // 行高
          // "insertImage", // 网络图片
          "deleteImage", // 删除图片
          "editImage", // 编辑图片
          "viewImageLink", // 查看链接
          "imageWidth30", // 图片宽度相对于编辑器宽度的百分比30
          "imageWidth50", // 图片宽度相对于编辑器宽度的百分比50
          "imageWidth100", // 图片宽度相对于编辑器宽度的百分比100
          "divider", // 分割线
          "emotion", // 表情
          "insertLink", // 插入链接
          "editLink", // 修改链接
          "unLink", // 取消链接
          "viewLink", // 查看链接
          // "codeBlock", // 代码块
          // "blockquote", // 引用
          "todo", // 待办
          "redo", // 重做
          "undo", // 撤销
          "fullScreen", // 全屏
          "enter", // 回车
          "bulletedList", // 无序列表
          "numberedList", // 有序列表
          "insertTable", // 插入表格
          "deleteTable", // 删除表格
          "insertTableRow", // 插入行
          "deleteTableRow", // 删除行
          "insertTableCol", // 插入列
          "deleteTableCol", // 删除列
          "tableHeader", // 表头
          "tableFullWidth", // 宽度自适应
          // "insertVideo", // 插入网络视频
          // "uploadVideo", // 上传视频
          // "editVideoSize", // 修改视频尺寸
          "uploadImage", // 上传图片
          // "codeSelectLang" // 选择语言
          // 对齐
          // {
          //   iconSvg:
          //       '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
          //   key: "group-justify",
          //   menuKeys: [
          //     "justifyLeft",
          //     "justifyRight",
          //     "justifyCenter",
          //     "justifyJustify",
          //   ],
          //   title: "对齐",
          // },
        ]
      },
      editorConfig: {
        placeholder: '请输入内容...' ,
        MENU_CONF: {
          uploadImage: {
            server: '/api/blade-resource/oss/endpoint/put-file',
            fieldName: 'file',
            // 单个文件的最大体积限制,默认为 2M
            maximgSize: 10 * 1024 * 1024, // 10M
            // 最多可上传几个文件,默认为 100
            maxNumberOfimgs: 10,
            // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
            allowedimgTypes: ['image/*'],
            // 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
            meta: {
              // token: 'xxx',
              // otherKey: 'yyy'
              // img:''
            },
            // 将 meta 拼接到 url 参数中,默认 false
            metaWithUrl: false,

            // 自定义增加 http  header
            headers: {
              Accept: 'text/x-json',
              // [website.tokenHeader]: `bearer ${getToken()}`,
              // Authorization: `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`
            },

            // 跨域是否传递 cookie ,默认为 false
            withCredentials: true,

            // 超时时间,默认为 10 秒
            timeout: 10 * 1000, //10 秒

            // 上传前
            onBeforeUpload(imgs) {
              loading = Loading.service({
                lock: true,
                text: '图片正在上传中,请耐心等待',
                spinner: "el-icon-loading"
              });
              return imgs;
            },
            // 自定义插入图片
            customInsert(res, insertFn) {
              console.log('customInsert', res)
              // 因为自定义插入导致onSuccess与onFailed回调函数不起作用,自己手动处理
              // 先关闭等待的ElMessage
              loading.close();

              if (res.code === 200) {
                Message({
                  message: '图片上传成功',
                  type: 'success'
                })
              } else {
                Message({
                  message: '图片上传失败,请重新尝试',
                  type: 'error'
                })
              }
              //获取文本中的img
              // var reg = /(?<=img src=").*?(?=" alt=)/g;
              // //this.formLabelAlign.content是文本内容
              // let addresslist=this.formLabelAlign.content.match(reg);
              // 从 res 中找到 url alt href ,然后插入图片

              let imgUrL = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
              function urlToBase64(url) {
                return new Promise((resolve, reject) => {
                  let image = new Image();

                  image.onload = function () {
                    let canvas = document.createElement("canvas");
                    canvas.width = this.naturalWidth;
                    canvas.height = this.naturalHeight;

                    // 将图片插入画布并开始绘制
                    canvas.getContext("2d").drawImage(image, 0, 0);

                    // result
                    let result = canvas.toDataURL("image/png");

                    resolve(result);
                  };

                  // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror

                  image.setAttribute("crossOrigin", "Anonymous");
                  image.src = url;

                  // 图片加载失败的错误处理
                  image.onerror = () => {
                    reject(new Error("urlToBase64 error"));
                  };
                });
              }
              urlToBase64(imgUrL).then((res) => {
                // 转化后的base64图片地址
                // console.log("base64", res);
                insertFn(res);
              });
            },

            // 单个文件上传成功之后
            onSuccess(img, res) {
              console.log(`${img.name} 上传成功`, res);
            },

            // 单个文件上传失败
            onFailed(img, res) {
              console.log(`${img.name} 上传失败`, res);
            },

            // 上传进度的回调函数
            onProgress(progress) {
              console.log('progress', progress);
              // progress 是 0-100 的数字
            },

            // 上传错误,或者触发 timeout 超时
            onError(img, err, res) {
              console.log(`${img.name} 上传出错`, err, res);
            }
          }
        }
      },
      mode: 'default', // or 'simple'
    }
},
  methods:{
    submit() {
      console.log("富文本提交内容");
      console.log(this.editor.getHtml());
      this.content = this.editor.getHtml();
    },
    show() {
      const toolbar = DomEditor.getToolbar(this.editor);
      const curToolbarConfig = toolbar.getConfig();
      console.log(curToolbarConfig.toolbarKeys);
    },
    onCreated(editor) {
        this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
    },
    beforeDestroy() {
        const editor = this.editor
        if (editor == null) return
        editor.destroy() // 组件销毁时,及时销毁编辑器
    }
}
}
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss" scoped>
::v-deep h5, .h5 {
  font-size: 14px;
}

::v-deep h4, .h4 {
  font-size: 16px;
  font-weight: bold;
}

::v-deep h3, .h3 {
  font-size: 18px;
  font-weight: bold;
}

::v-deep h2, .h2 {
  font-size: 20px;
  font-weight: bold;
}

::v-deep h1, .h1 {
  font-size: 22px;
  font-weight: bold;
}
::v-deep i {
  font-style: italic
}
::v-deep .w-e-toolbar .w-e-menu i {
  font-style: normal;
}
::v-deep ol {
  list-style-type: decimal;
}
::v-deep ol{
  margin: 10px 0 10px 22px;
  list-style-type: decimal;
}
::v-deep ul{
  margin: 10px 0 10px 22px;
  list-style-type: disc;
}
/* table 样式 */
::v-deep table {
  border-top: 1px solid #ccc;
  border-left: 1px solid #ccc;
}
::v-deep table td,
::v-deep table th {
  border-bottom: 1px solid #ccc;
  border-right: 1px solid #ccc;
  //padding: 3px 5px;
  width: 32px;
  height:32px;
}
::v-deep table th {
  border-bottom: 2px solid #ccc;
  text-align: center;
  background-color: #f1f1f1 ;
}

/* blockquote 样式 */
::v-deep blockquote {
  display: block;
  border-left: 8px solid #d0e5f2;
  padding: 5px 10px;
  margin: 10px 0;
  line-height: 1.4;
  min-height: 24px;
  font-size: 100%;
  background-color: #f1f1f1;
}

/* code 样式 */
::v-deep code {
  display: inline-block;
  *display: inline;
  *zoom: 1;
  background-color: #f1f1f1;
  border-radius: 3px;
  padding: 3px 5px;
  margin: 0 3px;
}
::v-deep pre code {
  display: block;
}
::v-deep a {
  // text-decoration: underline;
  color: #5592e5;
}
//::v-deep .w-e-bar-item button {
//  .title{
//    background: #fff;
//    margin-top: 10px;
//  }
//}

</style>