美文网首页前端开发那些事儿
Vue中富文本编辑器wangeditor的v-model封装

Vue中富文本编辑器wangeditor的v-model封装

作者: 第三只筷子 | 来源:发表于2020-08-05 20:33 被阅读0次

    以下代码实现只配置部分功能,更多功能扩展请查阅wangeditor官网

    一、下载依赖

    注意wangeditor全部是小写

    npm install wangeditor --save
    

    二、实现过程中遇到的坑

    1、当一个页面中使用到多个富文本组件时,会导致组件之间的id或者ref重复,导致渲染错误。

    解决方案:在组件内部使用随机字符串绑定组件的ref或者id


    2、在父组件中改变v-model绑定的值,富文本内容不改变。

    解决方案:使用watch进行监听value变化,具体看代码实现。


    3、每次调用editor.txt.html()方法,富文本中的光标就会出现在文末,导致在编辑富文本中间的内容时,出现鬼畜现象。

    解决方案:不要在editor.customConfig.onchange()中调用editor.txt.html()方法,而使用组件内部的一个content变量进行储存。然后watch content触发input事件,改变父组件的邦定值

    三、完整代码实现

    <template>
      <div>
        <div :ref="toolId" class="toolbar"></div>
        <div :ref="editorId" class="text"> <!--可使用 min-height 实现编辑区域自动增加高度-->
        </div>
      </div>
    </template>
    
    <script>
    import wangEditor from 'wangeditor'
    
    export default {
      name: 'rich-text',
      props: {
        value: String
      },
      data() {
        return {
          content: '',
          editor: {},
          toolId: '',
          editorId: ''
        }
      },
      computed: {
    
      },
      watch: {
        value(val) {
          if (val) {
            if (val !== this.content) {
              this.setContent(val);
            }
          } else {
            this.setContent('');
          }
        },
    
        content(val) {
          this.$emit('input', val);
        }
      },
      mounted() {
        this.toolId = this.randomString(12)
        this.editorId = this.randomString(12)
        this.content = this.value
        this.$nextTick(() => {
          this.editor = new wangEditor(this.$refs[this.toolId], this.$refs[this.editorId])
          this.editor.customConfig.onchange = (html) => {
            // 监控变化,同步更新到 textarea
            this.content = html
          }
          //配置图片上传服务器接口
          this.editor.customConfig.uploadImgServer = process.env.VUE_APP_BASE_API + '/file/upload/customizeDirUpload'
          // 文件名
          this.editor.customConfig.uploadFileName = 'file'
          // 配置上传图片请求头部
          // this.editor.customConfig.uploadImgHeaders = {}
          // 上传图片钩子函数
          this.editor.customConfig.uploadImgHooks = {
            before: function(xhr, editor, files) {
              // 图片上传之前触发
              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件
    
              // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
              // return {
              //     prevent: true,
              //     msg: '放弃上传'
              // }
            },
            success: function(xhr, editor, result) {
              // 图片上传并返回结果,图片插入成功之后触发
              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
              // alert('成功')
            },
            fail: function(xhr, editor, result) {
              // 图片上传并返回结果,但图片插入错误时触发
              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
            },
            error: function(xhr, editor) {
              // 图片上传出错时触发
              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
            },
            timeout: function(xhr, editor) {
              // 图片上传超时时触发
              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
            },
    
            // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
            // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
            customInsert: function(insertImg, result, editor) {
              // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
              // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
    
              // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
              var url = result.data
              insertImg(url)
    
              // result 必须是一个 JSON 格式字符串!!!否则报错
            }
          }
          this.editor.create()
          this.editor.txt.html(this.value)
        })
      },
      methods: {
        // 生成随机字符串id
        randomString(len) {
          len = len || 32
          let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /** **默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
          let maxPos = $chars.length
          let pwd = ''
          for (let i = 0; i < len; i++) {
            pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
          }
          return 'a' + pwd
        },
        setContent(val) {
          this.editor.txt.html(val)
        }
      }
    }
    </script>
    
    <style scoped>
      .toolbar {
        border: 1px solid #ccc;
      }
      .text {
        border: 1px solid #ccc;
        min-height: 200px;
      }
    </style>
    
    

    四、使用

    import导入组件后,和使用输入框一样使用即可:

    <rich-text v-model="html"></rich-text>
    

    相关文章

      网友评论

        本文标题:Vue中富文本编辑器wangeditor的v-model封装

        本文链接:https://www.haomeiwen.com/subject/mmqprktx.html