一、安装
npm i vue-quill-editor -S
二、 引入
import { quillEditor } from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
export default {
components: {
quillEditor
}
}
三、 图片压缩并上传服务器
富文本上传后的图片是以base64的形式存储在数据库,这会造成数据库存储过大,所以选择将图片上传到服务器上,然后返回后端给的url链接,插入在富文本对应的位置。
引入vue-quill-editor 的 image扩展插件 quill-image-extend-module:
npm i quill-image-extend-module -S
import { quillEditor, Quill } from 'vue-quill-editor'
import {
container,
ImageExtend,
QuillWatch
} from 'quill-image-super-solution-module'
Quill.register('modules/ImageExtend', ImageExtend)
四、 全部代码
<template>
<div>
<!-- 富文本组件 -->
<quill-editor
ref="quillEditor"
v-model="content"
class="editor"
:options="editorOption"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@change="onEditorChange($event)"
/>
<input
id="upload"
type="file"
style="display: none"
accept="image/*"
@change="handleInputChange"
>
</div>
</template>
<script>
import { uploadImage } from '@/api/blob'
import { quillEditor, Quill } from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import {
container,
ImageExtend,
QuillWatch
} from 'quill-image-super-solution-module'
Quill.register('modules/ImageExtend', ImageExtend)
export default {
components: { quillEditor },
props: {
/* 编辑器的内容 */
value: {
type: String
},
/* 图片大小 */
size: {
type: Number,
default: 5
}
},
data() {
return {
content: this.value,
editorOption: {
modules: {
ImageExtend: {
loading: true,
name: 'file',
},
toolbar: {
container: container,
handlers: {
image: function(value) {
if (value) {
document.querySelector('#upload').click() // 劫持原来的图片点击按钮事件
} else {
this.quill.format('image', false)
}
}
}
}
}
}
}
},
watch: {
value: function() {
this.content = this.value
}
},
methods: {
onEditorBlur() {
// 失去焦点事件
},
onEditorFocus() {
// 获得焦点事件
},
onEditorChange() {
// 内容改变事件
this.$emit('change', this.content)
},
dataURItoBlob(dataURI, type) {
// atob用于解码使用 base-64 编码的字符串
var binary = atob(dataURI.split(',')[1])
var array = []
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i))
}
return new Blob([new Uint8Array(array)], { type: type })
},
handleInputChange(e) {
const file = e.target.files[0]
if (!/image\/\w+/.test(file.type)) {
this.$message.error('图片格式不正确')
return
}
const isLt5M = file.size / 1024 / 1024 < 5
if (!isLt5M) {
this.$message.error(`图片大小不能超过 ${this.size}MB!`)
return
}
const reader = new FileReader()
const image = new Image()
image.onload = () => {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
// 根据原图片大小和图片压缩配置确定压缩后图片的宽和高
const width = image.width * 0.5
const height = image.height * 0.5
canvas.width = width
canvas.height = height
// 清空canvas画布上填充的矩形
context.clearRect(0, 0, width, height)
// 将原图片按压缩后的尺寸大小绘制在canvas画布中
context.drawImage(image, 0, 0, width, height)
const dataUrl = canvas.toDataURL(file.type)
// 将base64格式的图片转换为Blob对象
const blobData = this.dataURItoBlob(dataUrl, file.type)
// 将文件流转换为formData对象
const formData = new FormData()
formData.append('file', blobData)
uploadImage(formData)
.then((res) => {
if (res.data.code === 200) {
const quill = this.$refs.quillEditor.quill
// 光标位置
const length = quill.getSelection().index
// 插入图片 图片地址
quill.insertEmbed(length, 'image', res.data.data)
// 调整光标后移一位
quill.setSelection(length + 1)
}
})
}
reader.onload = (e) => {
image.src = e.target.result
}
reader.readAsDataURL(file)
}
}
}
</script>
<style>
.quill-editor {
white-space: pre-wrap !important;
line-height: normal !important;
padding-bottom: 100px;
padding-left: 100px;
width: 100%;
height: 800px;
}
</style>