vue2使用TinyMCE7富文本编辑器实现拖拽插入内容功能

引入的方法步骤

vue2引入tinymce7最简单的方法

实现拖拽借鉴的思路

实现内容拖拽或添加 HTML 到 Tinymce 富文本编辑器的高级功能详解
需求场景:
请添加图片描述
从列表项拖拽进编辑器实现思路:

  1. 页面元素添加拖拽属性和拖拽事件, 利用 event.dataTransfer.setData 方法传递数据
<div
     draggable="true"
     @dragstart="(event) => onDragStart(event)"
   >
    onDragStart(event) {
      const html = `<span class="mceNonEditable field">[${event.target.lastChild.innerText}]</span>`
      event.dataTransfer.setData('text/html', html)
    },
  1. 在编辑器组件的 setup 配置项中, 注册 drop 事件, 在该事件中接收传递的数据, 并将数据内容插入编辑器中
const opts = {
    setup: (editor) => {
            editor.on('drop', function (event) {
	            event.preventDefault()
	            var htmlContent = event.dataTransfer.getData('text/html')
	            editor.insertContent(htmlContent)
          })
	}
}

去除菜单栏工具栏

 menubar: '',
 plugins: '',
 toolbar: [],
 elementpath: false,
 resize: 'false',

修改编辑器内部样式 (包括placeholder)

content_style:
  'p { margin:10px 0; color:#333; fontSize:15px; }' +
  'body { margin:10px; }' +
  '.mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before { color:#96a1af;font-size:13px; }', // 修改 placeholder 样式

坑: editor.insertContent 失效
原因: 当调用子组件的 getValue 方法时, 该方法中的 this.editor.selection.select(editBody) 会导致 insertContent 方法失效
解决: 监听 editor 的变动, 更新父组件的数据

获取编辑器纯文本

思路: 利用 getContent 方法进行纯文本格式化

getValue() {
  const text = this.editor.getContent({
  format: 'text',
  })
  return text
},

遇到的问题: 编辑器在激活之后, 光标会跑到最前端

解决方法:

    endCommand() {
      this.editor.selection.select(this.editor.getBody(), true)
      this.editor.selection.collapse(false)
      this.editor.focus()
    }, 

在点击计算字段列表项后, 调用 endCommand 方法, 即可使光标在最后端
请添加图片描述
参考:
在tinyMCE中, 如何设置以及获取光标位置

组件代码:

<template>
  <div style="height: 100%">
    <textarea ref="textarea" id="tinymce-editor"></textarea>
  </div>
</template>

<script>
import tinymce from 'tinymce/tinymce'
import 'tinymce/skins/ui/oxide/skin'
import 'tinymce/themes/silver/theme'
import 'tinymce/icons/default/icons'
import 'tinymce/models/dom/model'

export default {
  name: 'TinyEditor',
  components: {},
  props: {
    // value: String,
  },
  data() {
    return {
      editor: null,
      bookmark: null,
    }
  },
  watch: {
    // value: {
    //   handler() {
    //     this.setContent(this.value)
    //   },
    //   immediate: true,
    // },
  },
  mounted() {
    this.initializeEditor()
  },
  beforeDestroy() {
    this.editor?.destroy()
  },
  methods: {
    initializeEditor() {
      ;``
      const defaultOptions = {
        target: this.$refs.textarea,
        content_css: '/tinymce/skins/ui/oxide/content.css',
        menubar: '',
        plugins: '',
        toolbar: [],
        statusbar: false,
        // elementpath: false,
        // resize: false,
        resize: false,
        height: '100%',
        promotion: false,
        placeholder: '请选择计算函数或输入自定义计算方式',
        content_style:
          'p { margin:10px 0; color:#333; fontSize:15px; }' +
          'body { margin:10px; }' +
          '.mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before { color:#96a1af;font-size:13px; }',
        // 初始化前执行
        setup: (editor) => {
          this.editor = editor
          editor.on('input', () => {
            // console.log('触发了 input')
            this.$emit('handleContentChange', editor.getContent())
          })

          editor.on('change', () => {
            // console.log('触发了 change')
            this.$emit('handleContentChange', editor.getContent())
          })

          editor.on('blur', () => {
            // console.log('触发了 blur')
          })

          editor.on('dragover', function (event) {
            // console.log('dragover')
            event.preventDefault()
          })

          editor.on('drop', function (event) {
            // console.log('drop')
            event.preventDefault()
            var htmlContent = event.dataTransfer.getData('text/html')
            editor.insertContent(htmlContent)
          })
        },
        // 初始化结束后执行
        init_instance_callback: function (editor) {},
        save_onsavecallback: () => {
          // console.log('Saved')
        },
      }
      
      tinymce
        .init({
          ...defaultOptions,
        })
        .then(([editor]) => {
          this.editor = editor
          this.setContent(this.value)
          // editor.on('change keyup undo redo', () => {
          //   this.$emit('input', editor.getContent())
          // })
        })
    },
    // 获取编辑器纯文本
    getValue() {
      return this.editor.getContent({
        format: 'text',
      })
    },
    // 设置内容
    setContent(val) {
      const oldValue = this.editor?.getContent()
      if (typeof val === 'string' && val !== oldValue) {
        this.editor?.setContent(val)
        this.$emit('handleContentChange', val)
        this.bookmark = this.editor.selection.getBookmark(2)
      }
    },
    // 插入内容
    insertContent(val) {
      this.editor.insertContent(val)
    },
    // 将光标移至末端
    endCommand() {
      this.editor.selection.select(this.editor.getBody(), true)
      this.editor.selection.collapse(false)
      this.editor.focus()
    },
    // 聚焦
    focus() {
      this.editor.focus()
    },
  },
}
</script>

<style>
.tox-tinymce-aux {
  z-index: 10000 !important;
}
.tox .tox-number-input .tox-input-wrapper {
  display: none !important;
}
.tox-statusbar__branding {
  display: none !important;
}
.tox-editor-header {
  display: none !important;
}
.tox-tinymce {
  border: 1px solid #d5e1f7 !important;
  border-radius: 4px !important;
}

/* .mce-content-body *[contentEditable='false'][data-mce-selected] {
  outline: 3px solid #b4d7ff8c;
  border-radius: 4px;
  background: #b4d7ff8c;
} */
</style>


  • 27
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值