vue 封装 wangEditor

wangEditor 是一款比较流行的富文本编辑器,它比较轻量级,并且很容易通过css来定制化样式
下面的代码是用ts写的,如果是js的话,转换一下就行了,只是语法不一样

<template>
  <div class="editor">
    <div
        ref="toolbar"
        class="editor_toolbar"
        :class="toolbarClass"
    ></div>
    <div
        ref="editor"
        class="editor_text"
        :class="textClass"
    ></div>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator'
import WangEditor from 'wangeditor'

@Component({
  components: {
  }
})
export default class Editor extends Vue {
  @Model('update', {
      type: String,
      default: ''
  })
  public content!: string

  @Prop({
      default: false
  })
  public isClear?: boolean

  @Prop({
    default: () => {
        return [
          'bold', // 粗体
          'italic', // 斜体
          'head', // 标题
          'quote', // 引用
          // 'code', // 插入代码
          'list', // 列表
          // 'fontSize', // 字号
          // 'fontName', // 字体
          'underline', // 下划线
          'strikeThrough', // 删除线
          // 'foreColor', // 文字颜色
          // 'backColor', // 背景颜色
          'link', // 插入链接
          // 'justify', // 对齐方式
        //   'emoticon', // 表情
          'image', // 插入图片
          'table', // 表格
          'video', // 插入视频
          'undo', // 撤销
          'redo', // 重复
          'fullscreen' // 全屏
        ]
    }
  })
  public menus?: []

  @Prop({
      default: ''
  })
  public toolbarClass?: boolean

  @Prop({
      default: ''
  })
  public textClass?: boolean

  public editor: any = null
  public info: any = null
  public flag: boolean = false

  @Watch('isClear')
  public isClearChange(val: boolean) {
      const me: any = this
      if (val) {
          me.editor.txt.clear()
          me.info = null
      }
  }

  @Watch('content', {deep: true, immediate: true})
  public contentChange(val: string) {
    const me: any = this

    me.$nextTick(() => {
      if (val !== me.editor.txt.html() && !me.flag) {
        me.editor.txt.html(val.replace(/\#image/g, 'data:image'))
      }

      me.flag = false
    })
  }

  public seteditor() {
    const me: any = this
    me.editor = new WangEditor(me.$refs.toolbar, me.$refs.editor)
    // me.editor.customConfig.pasteFilterStyle = false
    me.editor.customConfig.uploadImgShowBase64 = true // base 64 存储图片
    // me.editor.customConfig.uploadImgServer = 'http://otp.cdinfotech.top/file/upload_images'// 配置服务器端地址
    // me.editor.customConfig.uploadImgHeaders = { }// 自定义 header
    me.editor.customConfig.uploadFileName = 'file' // 后端接受上传文件的参数名
    me.editor.customConfig.uploadImgMaxSize = 2 * 1024 * 1024 // 将图片大小限制为 2M
    me.editor.customConfig.uploadImgMaxLength = 6 // 限制一次最多上传 3 张图片
    me.editor.customConfig.uploadImgTimeout = 3 * 60 * 1000 // 设置超时时间

    me.editor.customConfig.menus = me.menus

    me.editor.customConfig.uploadImgHooks = {
        faile: me.uploadImgFail,
        success: me.uploadImgSuccess,
        timeout: me.uploadImgTimeout,
        error: me.uploadImgError,
        customInsert: me.uploadImgCustomInsert,
    }

    me.editor.customConfig.onchange = me.initContent

    me.editor.customConfig.pasteTextHandle = me.pasteTextHandler

    // 创建富文本编辑器
    me.editor.create()
  }

  public pasteTextHandler(content: string) {
    // content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回
    if (content === '' && !content) {
      return ''
    }
    let str = content
    str = str.replace(/<xml>[\s\S]*?<\/xml>/ig, '')
    str = str.replace(/<style>[\s\S]*?<\/style>/ig, '')
    str = str.replace(/<\/?[^>]*>/g, '')
    str = str.replace(/[ | ]*\n/g, '\n')
    str = str.replace(/&nbsp;/ig, '')
    // console.log('****', content)
    // console.log('****', str)
    return str
  }

  public uploadImgFail(xhr: any, editor: any, res: any) {
      const me: any = this
  }

  public uploadImgSuccess(xhr: any, editor: any, res: any) {
      const me: any = this
  }

  public uploadImgTimeout(xhr: any, editor: any) {
      const me: any = this
  }

  public uploadImgError(xhr: any, editor: any) {
      const me: any = this
  }

  public uploadImgCustomInsert(insertImg: any, result: any, editor: any) {
      const me: any = this
      const url = 'http://otp.cdinfotech.top' + result.url
      insertImg(url)
  }

  public initContent(html: string) {
    const me: any = this
    me.info = html // 绑定当前值
    me.flag = true
    // me.editor.txt.html(html)
    me.$emit('update', me.info) // 将内容同步到父组件中
  }

  public mounted() {
    const me: any = this
    me.seteditor()
    me.editor.txt.html(this.content.replace(/\#image/g, 'data:image'))
  }
}
</script>

<style lang="scss" scoped>
.editor {
  position: relative;
  z-index: 0;
  width: 100%;
  margin: 0 auto;
}

.editor_toolbar {
  border: 1px solid #CCC;
}

.editor_text {
  min-height: 120px;
  border: 1px solid #CCC;
  border-top: none;
}
</style>

在组件中使用

<template>
  <div>
    <editor
      v-model="content"
      @change="contentChange"
    ></editor>
  </div>
</template>

<script>
import { Vue, Component } from 'vue-property-decorator'
export default Vue.extend({
  data() {
    return {
       content: '',
    }
  },
  methods: {
    contentChange() {}
  }
})
</script>
上一篇:UEditor之——图片上传组件大小4M的限制


下一篇:Vue笔记:bin-code-editor使用