需求:使用能插入图片的编辑器将文字和图片混合作为一道作业题目
由于是在原来项目的基础上做的修改,老项目使用的UEditor
编辑器,为了将题目中的公式转为图片,方便新增数据,于是 前后端按照官网写法配置了PHP
插入图片,会报错 跨域
所以我们考虑使用Quill
代替UEditor
,因为项目中很多地方都使用了UEditor
,因此我们直接修改UEditor
组件的代码为了兼容项目中出现的UEditor
语法和Quill
图片上传模式
修改UEditor
组件的代码,以兼容项目中对UEditor API
的使用手法和Quill
自身的图片上传模式
目的:尽可能少的修改代码,以达到全局文本编辑器的修改
大致流程图如下所示
UEditor
组件源代码(如下所示)
<template>
<div>
<script :id="randomId" type="text/plain" style="height: 300px;"></script>
</div>
</template>
<script>
export default {
name: 'UE',
props: {
value: {
default: function () {
return ''
}
}
},
data () {
return {
randomId: 'editor_' + Math.random() * 100000000000000000,
// 编辑器实例
instance: null,
ready: false
}
},
watch: {
value: function (val, oldVal) {
if (val != null && this.ready) {
// eslint-disable-next-line no-undef
this.instance = UE.getEditor(this.randomId)
this.instance.setContent(val)
}
}
},
mounted () {
this.initEditor()
},
beforeDestroy () {
if (this.instance !== null && this.instance.destroy) {
this.instance.destroy()
}
},
methods: {
initEditor () {
this.$nextTick(() => {
// eslint-disable-next-line no-undef
this.instance = UE.getEditor(this.randomId)
this.instance.addListener('ready', () => {
this.ready = true
this.$emit('ready', this.instance)
})
})
},
getUEContent () {
return this.instance.getContent()
},
setText (con) {
// eslint-disable-next-line no-undef
this.instance = UE.getEditor(this.randomId)
this.instance.setContent(con)
}
}
}
</script>
修改后的UEditor
组件代码(实则为Quill
组件代码了)
<template>
<div class="edit_container">
<quill-editor
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@change="onEditorChange($event)"
@ready="onEditorReady($event)"
>
</quill-editor>
</div>
</template>
<script>
import {quillEditor} from 'vue-quill-editor' // 调用编辑器
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import resizeImage from 'quill-image-resize-module' // 图片缩放组件引用
import {ImageDrop} from 'quill-image-drop-module'
import Quill from "quill/quill";
Quill.register('modules/imageDrop', ImageDrop) // 注册
Quill.register('modules/resizeImage ', resizeImage)
export default {
name: 'UE',
props: ['initValue'],
components: {
quillEditor
},
watch:{
initValue:{
handler(newInitValue){
this.content=newInitValue;
},
deep:true,
immediate:true,
}
},
data() {
return {
//randomId: 'editor_' + Math.random() * 100000000000000000,
// 编辑器实例
instance: null,
ready: false,
content: this._props.initValue || ``,
editorOption: {
placeholder: '请在这里输入',
modules: {
imageResize: { // 放大缩小
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white'
},
modules: ['Resize', 'DisplaySize', 'Toolbar']
},
toolbar: [
['bold', 'italic', 'underline', 'strike'], // 加粗,斜体,下划线,删除线
['blockquote', 'code-block'], // 引用,代码块
[{'header': 1}, {'header': 2}], // 标题,键值对的形式;1、2表示字体大小
[{'list': 'ordered'}, {'list': 'bullet'}], // 列表
[{'script': 'sub'}, {'script': 'super'}], // 上下标
[{'indent': '-1'}, {'indent': '+1'}], // 缩进
[{'direction': 'rtl'}], // 文本方向
[{'size': ['small', false, 'large', 'huge']}], // 字体大小
[{'header': [1, 2, 3, 4, 5, 6, false]}], // 几级标题
[{'color': []}, {'background': []}], // 字体颜色,字体背景颜色
[{'align': []}], // 对齐方式
['image'] // 上传图片
]
}
}
}
},
// watch: {
// value: function (val, oldVal) {
// if (val != null && this.ready) {
// // eslint-disable-next-line no-undef
// this.instance = UE.getEditor(this.randomId)
// this.instance.setContent(val)
// }
// }
// },
mounted() {
this.initEditor()
},
beforeDestroy() {
if (this.instance !== null && this.instance.destroy) {
this.instance.destroy()
}
},
computed: {
editor() {
return this.$refs.myQuillEditor.quill
}
},
methods: {
initEditor() {
/* this.instance = this.$refs.randomId11.quill;
this.ready = true
const content = ''// 请求后台返回的内容字符串
this.content = this.escapeStringHTML(content)
this.$emit('ready', this.instance)*/
},
getUEContent() {
return this.content
},
/* setText(con) {
this.instance = UE.getEditor(this.randomId)
this.instance.setContent(con)
},*/
onEditorBlur() {
}, // 失去焦点事件
onEditorFocus() {
}, // 获得焦点事件
onEditorChange({quill, html, text}) {
this.content=html
this.$emit('change', html)
}, // 内容改变事件
// 准备富文本编辑器
onEditorReady(quill) {
this.$emit('ready', quill)
},
// 转码
escapeStringHTML(str) {
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
return str
},
/*setContent(content) {
this.content = content;
}*/
}
}
</script>
<style>
.editor {
line-height: normal !important;
height: 500px;
}
.edit_container {
display: flex;
margin: 0 auto;
width: 650px;
height: 300px;
}
.ql-snow .ql-tooltip[data-mode=link]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: '保存';
padding-right: 0px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
content: '32px';
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: '标题6';
}
</style>
用法如下
<Ueditor @ready="editorReady" @change="callbackChangeEditor" :initValue="bufsEditorContent"/>
需定义 editorReady
和 callbackChangeEditor
事件
//编辑器内文本变化触发onchange事件 的回调处理函数
callbackChangeEditor(value) {
this.richEditor.object[this.richEditor.parameterName] = escapeStringHTML(value + '') || ''
},
//初始化 编辑器实例时的回调处理函数
editorReady(instance) {
this.richEditor.instance = instance
let currentContent = this.richEditor.object[this.richEditor.parameterName]
//bufsEditorContent 是定义在data方法中的变量,用来和编辑器内容进行双向绑定
//赋值
this.bufsEditorContent = currentContent;
// 光标定位到Ueditor
this.richEditor.instance.focus(true)
},
修改配置,成功上传图片并展示