我们在使用该富文本框的时候,直接剪切图片到编辑区,默认是插入了 base64的图片格式,如果是单张图片还好,多张图片会导致数据库字段储存过长,在加载接口数据也很耗时,so。。。要么我们禁用粘贴复制图片的功能,给个友情提示,要么我们拦截图片上传到服务器拿到URL地址再插入到编辑区。
插件地址: https://quilljs.com/
vue初始化插件,提取重要部分,其他代码忽略。。。。
//html代码
<div class="editor" ref="editor" :style="styles"
@dragover.prevent="handleDragOver"
@drop.prevent="handleDrop"
></div>
//初始化
const editor = this.$refs.editor;
this.Quill = new Quill(editor, this.options);
第一种禁用粘贴复制图片
data() {
return {
content: ``, // 富文本编辑器默认内容
options: {
// 富文本编辑器配置
modules: {
clipboard: {
// 粘贴版,处理粘贴时候带图片
matchers: [[Node.ELEMENT_NODE, this.handleCustomMatcher]],
},
//工具栏定义的
toolbar: [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
[{ indent: "-1" }, { indent: "+1" }], // 缩进
[{ size: ["small", false, "large", "huge"] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ align: [] }], // 对齐方式
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
],
},
//主题
theme: "snow",
placeholder: "请输入正文"
}
};
},
自定义的匹配器method 下
handleCustomMatcher (node, Delta) {
let ops = []
Delta.ops.forEach(op => {
if (op.insert && typeof op.insert === 'string') {// 如果粘贴了图片,这里会是一个对象,所以可以这样处理
ops.push({
insert: op.insert,
})
} else {
if (op.insert.image.includes('file://') || op.insert.image.includes('data:image/') ) { //本地图片会使文件file开头 和 base64 开头data:image/
this.$message.warning('不允许粘贴图片,请手动上传')
} else {
ops.push({
insert: op.insert,
})
}
}
})
Delta.ops = ops
return Delta
}
第二种获取到图片,然后上传到服务器,拿到URL再插入编辑器中
handleCustomMatcher (node, Delta) {
let ops = []
Delta.ops.forEach(op => {
if (op.insert && typeof op.insert === 'string') {// 如果粘贴了图片,这里会是一个对象,所以可以这样处理
ops.push({
insert: op.insert,
})
} else {
if (op.insert.image.includes('file://') || op.insert.image.includes('data:image/') ) { //本地图片会使文件file开头 和 base64 开头data:image/
//处理图片上传到服务器
//request是我的自定义函数,请替换成您的上传函数 Promise
request({
url: '/common/uploadBase64',
method: 'post',
data: { file: op.insert.image }//base64 数据
}).then(url => {
let length = this.Quill.getSelection().index; //光标位置
this.Quill.insertEmbed(length, "image", url ); // 插入图片 图片地址
this.Quill.setSelection(length + 1);
}).catch(err => {
this.$message.error(err)
})
} else {
ops.push({
insert: op.insert,
})
}
}
})
Delta.ops = ops
return Delta
}
ok 这里基本使用完成啦。。。。
其他功能:如果我们想直接拖动图片到编辑区中,然后上传呢?开头在初始化的时候定义了
@dragover.prevent="handleDragOver"
@drop.prevent="handleDrop"
拖动函数,哈哈,我们监听这2个函数即可,代码如下:
// 处理拖拽事件目标元素
handleDragOver(event) {
//console.log(event);
},
//作用于目标元素
handleDrop(event) {
const files = event.dataTransfer.files;
if (files.length > 0) {
console.log(files);
const formData = new FormData();
formData.append("file", files[0]);
//request是我的自定义函数,请替换成您的上传函数 Promise
request({
url: '/common/upload',
method: "post",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
}
}).then((res) => {
if (res.code == 200) {
let length = this.Quill.getSelection().index; //光标位置
this.Quill.insertEmbed(length, "image", url ); // 插入图片 图片地址
this.Quill.setSelection(length + 1);
} else {
this.$message.error("图片插入失败");
}
})
}
},
wow! 这样我们就完成了,该插件的改造了,其它的待续………
拖拽事件彩蛋1:
被拖动元素相关事件:
事件 | 描述 |
dragstart | 用户开始拖动元素时触发 |
drag | 元素正在拖动时触发 |
dragend | 用户完成元素拖动后触发 |
容器相关事件如下所示:
事件 | 描述 |
dragenter | 当被鼠标拖动的对象进入目标容器时触发此事件 |
dragover | 当被拖动的对象在目标容器范围内拖动时触发此事件 |
dragleave | 当被鼠标拖动的对象离开目标容器时触发此事件 |
drop | 在一个拖动过程中,释放鼠标键到目标容器时触发此事件 |