引入的方法步骤
实现拖拽借鉴的思路
实现内容拖拽或添加 HTML 到 Tinymce 富文本编辑器的高级功能详解
需求场景:
从列表项拖拽进编辑器实现思路:
- 页面元素添加拖拽属性和拖拽事件, 利用
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)
},
- 在编辑器组件的
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>